Javascript 什么';nodejs中这两个异步函数的区别是什么?
//结果是1 3 2 4Javascript 什么';nodejs中这两个异步函数的区别是什么?,javascript,node.js,asynchronous,event-loop,libuv,Javascript,Node.js,Asynchronous,Event Loop,Libuv,//结果是1 3 2 4 const fs = require("fs"); fs.readFile("aa.js", () => { console.log("1"); process.nextTick(() => { console.log("3"); }); }); fs.readFile("aa.js", () => { console.log("2"); process.nextTick(() => { console.l
const fs = require("fs");
fs.readFile("aa.js", () => {
console.log("1");
process.nextTick(() => {
console.log("3");
});
});
fs.readFile("aa.js", () => {
console.log("2");
process.nextTick(() => {
console.log("4");
});
});
//结果是1234
依我看,这两个异步回调应该表现相同,
但结果不同,,
幕后原因是什么?第一个原因是两个完全独立的异步
fs.readFile()
操作之间的竞争。无论哪一个先完成,都可能先获得两个控制台日志。因为这些操作需要一些可测量的时间,而且它们都必须完成完全相同的工作量,所以很可能你首先开始的操作将首先完成,这就是你所看到的。但是,从技术上讲,这是两个异步操作之间的不确定竞争,它们可以以任何顺序完成。因为一个可能比另一个稍早完成,所以它的完成回调将在另一个之前调用,并且第二个可能在下一个勾号发生之前还没有完成,所以这就是为什么您会看到来自第一个完成的日志消息的原因
您的第二个侦听器是完全相同事件的两个事件侦听器。因此,这两个侦听器保证在同一个勾号上依次调用。当一个事件监听器对象发出一个事件时,它会同步地逐个调用该事件的所有监听器,所有监听器都在同一个刻度上。这就是为什么在未来的节拍中会出现1
,然后在3
和4
之前出现2
不应将eventEmitter对象与事件队列混淆。它们不是一回事。在本例中,您的服务器对象是eventEmitter的子类。服务器内部的某些代码决定向服务器的eventEmitter的侦听器发出侦听
事件。发出事件的决定可能是来自事件队列的某个异步操作的结果。但是,要真正发送到eventEmitter,这只是对注册侦听器的同步函数调用。此操作不涉及事件队列。在eventEmitter代码内部,它实际上有一个for
循环,该循环通过匹配的事件处理程序循环并逐个调用。这就是为什么会得到1
,然后得到2
事实上,这里是EventEmitter类定义中的.emit()
方法的内部,它显示了通过匹配的侦听器循环并同步调用它们。下面是一段逐个调用每个侦听器的代码:
const net = require("net");
const server = net.createServer(() => {}).listen(8080);
server.on("listening", () => {
console.log("1");
process.nextTick(() => {
console.log("3");
});
});
server.on("listening", () => {
console.log("2");
process.nextTick(() => {
console.log("4");
});
});
const len=handler.length;
const listeners=arrayClone(处理器,len);
对于(变量i=0;i
}当侦听事件激发时,两个侦听处理程序都被添加到事件队列中-直到事件队列清空后,
下一个勾号队列才会被处理
const len = handler.length;
const listeners = arrayClone(handler, len);
for (var i = 0; i < len; ++i)
Reflect.apply(listeners[i], this, args);