我对这个问题的了解程度很低,所以请耐心等待。
我理解可能需要额外延迟的函数,如数据库读/写,文件读取等,应该异步运行,以免阻塞。
我的搜索后没有真正回答的是:
像简单的for循环这样的东西应该异步运行吗?它可能很简单:
function a() {
var a = 0;
for(i=0; i<10000000; i++) {
a++;
};
};
因为这样的事情可能需要几毫秒,是否应该放在Node.js承诺中呢?
我是否正确地假设如果我不这样做,那么肯定会有阻塞,虽然只有几毫秒?
答案 0 :(得分:2)
我不确定我是否理解正确,但我认为这不会像你期望的那样奏效。在未来“包装”该函数将使调用异步但不是函数本身。
假设以下情形:
f1();
a();
f2();
f3();
// (...)
如果a()
是同步f2()
,则只会在a()
完成后执行(即你的for循环)。现在,如果a()
是异步的,这意味着f2()
将立即执行,因此它不会阻止执行。
但是由于NodeJS是单线程的,并且所有代码都是在循环中执行的,每当for循环执行时,它将从开始到结束(从迭代0到9999999)运行而不会暂停,因此它将阻止其他操作那个时候。
所以使用promises只会在代码阻止你的app时延迟。
如果该功能只需要几毫秒才能完成,这可能不会产生太大的影响。但是,如果需要几秒或几分钟,则需要确保该任务使用nextTick
或使用async.eachSeries之类的内容不时向NodeJS提供控制权。
This article解释这是一些细节。
答案 1 :(得分:1)
因为这样的事情可能需要几毫秒,是否应该放在Node.js承诺中呢?
理想情况下,是的。节点,或者更确切地说是V8引擎,是为高吞吐量/可扩展性而设计的,因此任何有效阻止执行的都应该异步运行。
答案 2 :(得分:0)
“异步运行”和“异步运行”之间存在差异。
就像你提到的那样,NodeJS在运行循环时会阻塞。这意味着没有其他任何东西可以在CPU上运行。调用该函数的位置并不重要,它将使用所有CPU周期直到完成。
如果通过Promise或async
库异步运行它,只要for-loop
运行,它就会一直运行直到完成。此时没有其他任何东西会运行,它会阻止所有其他操作。如果你为异步编写它,你可以将循环分解为更小的块,这些块将以串行或并行的方式异步运行,每个块都足够小,不会严重影响正在发生的其他事情。
几毫秒太多了?取决于您的应用程序。事情是,处理将必须在某个时间发生,所以没有必要将其分解得太多。请注意,循环(以及其他一些结构,如Array.forEach
)会阻止您处理其他事件,尽力避免出现问题,并尽可能地测试您的应用。
答案 3 :(得分:0)
Nodejs与大多数其他编程环境的不同之处在于,Web应用程序的所有用户共享同一个线程。这意味着如果一个用户从数据库请求信息,则不希望所有其他用户在处理之前排队等待数据库请求完成,比如其他用户的页面加载请求。因此,尽可能多地释放线程以便Node可以为其他用户请求提供服务。
现在释放线程意味着什么?从本质上讲,V8引擎(支持nodejs)以逐步的方式执行命令,正如大多数程序员习惯的那样。但是,执行线程可能会到达等待来自其他源的输入的点。如果以同步方式写入函数,则执行只是在那里等待,直到接收到输入,然后继续处理程序的其余部分。但是,如果函数是以非阻塞(异步)方式编写的,则释放线程以执行任何其他可用的函数(例如,来自其他用户的新请求)。以非阻塞模式编写代码可以在多用户环境中提高执行效率。
现在针对您的具体问题,要问的问题是,如果您创建函数,a(),异步,您是否可以释放执行线程?答案是不。这是因为节点仍在执行for循环,因此不能同时执行其他功能,并且没有任何点暂停执行,等待另一个系统提供输入。所以,不要让你的for循环异步。它只会增加代码的复杂性,并且对执行效率没有任何价值。相反,只是尝试确保尽可能有效地执行for循环。