我正在尝试扩展我的nodejs应用程序,以便它可以有效地同时处理多个请求。实现此目标的一种方法是通过代码优化,而我想知道如何使耗时的请求异步进行,诺言是唯一的方法吗?还是有另一种机制可以实现相同目标?
我已经将promise用于异步任务,但是据我所了解的promise,真正的异步部分是then和catch处理程序。当创建一个promise时,executor函数将由主线程执行,直到执行一些异步任务(setTimeout等)为止。
发送电子邮件的示例代码
app.route('/api/contact/sendEmail')
.post((req, res) =>{
sendEmail(req).then( () =>{
res.status(200);
res.json({
sent: true
});
}).catch(emailError=> {
//Custom error send bad request.
if(emailError.code === 900) {
res.status(400);
res.json({
errorCode: emailError.code,
message: emailError.message
});
}else {
res.status(500);
res.json({
errorCode: emailError.code
});
}
});
});
不会阻塞线程发送响应,但是直到sendEmail没有到达实际的异步部分之前,主线程才会被阻塞
答案 0 :(得分:2)
由于您没有提供有关正在使用的库/功能的详细信息,因此很难回答您的问题。 sendMail
函数的来源,app
是什么,以及在什么时候您认为某些内容受阻。
但是,通常,Node.JS中的代码始终在主线程中执行。这意味着,.js文件的每一行都位于主线程中,无论是否存在“异步”。
现在,要实际允许某些东西“异步”(即:在执行其他代码的同时执行 ),必须有一种方法可以将内容推到另一个线程中执行。这就是实际上在Node.JS中实际发生的情况。 Node.JS使用libuv
/ libev
来实现事件循环来处理任务。它还具有许多后台/工作线程(默认情况下为4),这些线程执行阻止任务,例如网络或文件I / O。
但是,这是从Node.JS开发人员那里抽象出来的,因为它被嵌入在相应的 module 的实现中。例如,内置文件系统或网络模块将在后台线程中执行其任务(除非您使用-sync
函数变体之一)。
如果您使用的是第三方模块,则取决于它是否用C / C ++编写并使用libuv
来访问工作线程并进行后台处理。如果不是,那么您的第三方模块将在主线程上与您的代码相同地执行代码,如果是,则执行实际上是在后台线程中“异步”完成的。
也请参见以下非常有用的主题:How the single threaded non blocking IO model works in Node.js
这对您有什么帮助?
基本上,我想告诉您这一切都取决于您使用的功能/模块,以及它们是否被实现为后台操作(使用libuv
)。最重要的是,您自己无法进行任何异步/同步操作,您必须使用该功能/模块实现的功能。
出于完整性考虑,我想提到Node.JS 11引入了worker_threads
模块,该模块允许在javascript代码中使用线程,从而使您可以在后台线程中放置某些内容而不阻塞主线程。 。请注意,模块的稳定性仍然是“实验性的”。
边注
您真的确定您的代码阻塞了主线程吗?因为如前所述,网络IO始终发生在后台线程中,所以sendMail
不太可能阻塞主线程(假设sendMail
的工作是做网络IO)。
您是怎么发现它阻塞的?