Node.js事件会发生什么?

5

我有一个 Express 应用程序,当解析请求到达特定路由时会使用事件发射器。当接收到请求时,将调用 emit 函数,在处理程序中运行代码。此代码大约需要 5 秒钟才能完成。当 Express 端点同时接收到 10 个或更多请求时,会发生什么?

这些事件会被放入调用堆栈中,并按照它们被放入调用堆栈的顺序完成吗?

谢谢。

status.emit('newCompletion')
1个回答

5

EventEmitter事件是同步的。它们在调用.emit()时执行。您可以将它们视为函数调用,其中调用.emit()只是立即调用任何匹配侦听器的函数。

这些事件会被放入调用堆栈中,并按照它们被放入调用堆栈的顺序完成吗?

它们是同步执行的。您使用的措辞让我想到您认为有一些事件排队等待处理。实际上并没有。您调用.emit(),任何该事件名称的侦听器都会立即调用(甚至在.emit()返回之前)。

我有一个使用事件发射器来解决特定路由请求的 Express 应用程序。当接收到请求时,会调用 emit,从而在处理程序中运行代码。此代码需要大约 5 秒钟才能完成。当 Express 端点同时接收到 10 或更多请求时会发生什么?

如果五秒钟的完成时间是同步代码,则在这五秒钟内不会发生其他事情。没有其他传入请求将被处理(它们可能会在操作系统中的某个传入 TCP 队列或事件队列中等待)。因此,一个请求将运行其五秒钟的代码,通过完成其执行将控制权返回给 Node.js,然后 Node.js 将从事件队列中获取下一个事件并处理下一个请求。

如果这5秒钟的完成时间包含一些异步操作,因此它是5秒的时钟时间,但不是5秒的 CPU 时间,则情况会更加复杂。只要第一个请求触发了一个带有注册回调函数的异步操作,然后将控制权返回给 Node.js,它将从事件队列中获取下一个事件并开始运行该请求处理程序。那将一直运行,直到将控制权返回给系统。任何.emit()在这两个请求中都是同步的,并且不会导致除执行该事件的处理程序之外的任何其他事情发生。

您可以看到.emit()在这里是同步的,因为它先于其他任务和微任务:

let em = new EventEmitter();
em.on("hello", function() {
    console.log("hello");
});


// schedule "immediate" task
setTimeout(function() {
    console.log("timer");
}, 0)

// schedule "immediate" micro-task
Promise.resolve().then(function() {
    console.log("promise");
});

em.emit("hello");
console.log("ready");
<script src="https://cdnjs.cloudflare.com/ajax/libs/EventEmitter/5.2.2/EventEmitter.js"></script>


1
我理解你的意思。我曾认为当emit被调用时,路由中的代码会继续执行。我想我需要一些工作队列,以便在收到请求时,该路由可以响应已接收到请求,而工作在后台继续进行。谢谢。 - Cazineer
@Kainan - node.js的JavaScript是单线程的。因此,如果node.js正在忙于运行5秒钟的同步代码,则在此期间不会发生任何其他事情。实现同步代码的“后台处理”的唯一方法是使用其他进程来执行您的工作。然后,主进程可以自由处理传入的请求,而其他进程可以执行工作。您可能会使用某种工作队列来完成这项工作。 - jfriend00
@Kainan - 但是,如果你的5秒工作大多与I/O相关(数据库、文件、网络等),那么你可以编写适当的异步代码,因为它们都花费大部分时间等待外部事物完成,所以你将拥有许多请求处理程序“在飞行”中,因为没有一个实际上使用了很多CPU - 即使使用node.js单线程,也会完成很多工作。 - jfriend00
明白了,谢谢 @friend00。感谢你的帮助。 - Cazineer

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接