我的理解是(非集群)nodejs 程序中的所有代码都在同一个线程中运行。鉴于此,我希望所有此类代码都将作为同一根事件循环的子代码运行,因此如果检查堆栈跟踪以查找在不同回调中运行的代码,我们最终仍会回溯到同一条目(该事件循环的“调度事件”行)。但事实并非如此,我不明白为什么。
考虑以下:
function printStackTrace() {
console.log(new Error().stack);
}
printStackTrace();
setTimeout(printStackTrace, 1000);
运行产生:
Error
at printStackTrace (/tmp/node/test.js:4:17)
at Object.<anonymous> (/tmp/node/test.js:7:1)
at Module._compile (module.js:446:26)
at Object..js (module.js:464:10)
at Module.load (module.js:353:32)
at Function._load (module.js:311:12)
at Array.0 (module.js:484:10)
at EventEmitter._tickCallback (node.js:190:39)
Error
at Object.printStackTrace [as _onTimeout] (/tmp/node/test.js:4:17)
at Timer.ontimeout (timers.js:94:19)
并且简单地console.log(new Error().stack);
在 REPL 中运行仍然会给出不同的根:
Error
at repl:1:13
at REPLServer.eval (repl.js:80:21)
at repl.js:190:20
at REPLServer.eval (repl.js:87:5)
at Interface.<anonymous> (repl.js:182:12)
at Interface.emit (events.js:67:17)
at Interface._onLine (readline.js:162:10)
at Interface._line (readline.js:426:8)
at Interface._ttyWrite (readline.js:603:14)
at ReadStream.<anonymous> (readline.js:82:12)
因此,每个项目的根(最底部)项目是不同的(分别在 EventEmitter、Timer 和 ReadStream 中)。其他回调(例如 net)也是如此。
所以我想要么
- 事件循环是本机 (C++) 代码,因此它不会显示在堆栈跟踪中,并且异步服务的基本提供者(repl.js、timers.js 等)使用本机 v8 api 调用向它注册自己.
- 事件循环是 JavaScript,但
Error()
有特殊的代码来隐藏它(作为不必要的实现细节)
其中哪一个(如果有的话)是这种情况,一般来说,我可以在 nodejs(编辑:或 v8)源中的哪个位置读取真正的根事件循环的实现?