Node.js setImmediate在I / Ocallback之前执行(Event Loop)
看看下面的代码:
var fs = require('fs'); var pos = 0; fs.stat(__filename, function() { console.log(++pos + " FIRST STAT"); }); fs.stat(__filename, function() { console.log(++pos + " LAST STAT"); }); setImmediate(function() { console.log(++pos + " IMMEDIATE") })
当我执行这个代码时,显示以下结果:
正如Node.js 文档所解释的,setImmediate是在I / Ocallback之后执行的,但在本例中,在I / Ocallback之前正在执行setImmediate,我错过了什么?
您期待的结果将需要fs.stat方法立即返回 – 基本上在当前事件循环结束之前。 但是,您的磁盘需要2ms才能完成I / O操作。 足够的时间来运行相当多的事件循环。 发生什么(最可能是)现在是:
Loop 0 starts fs.stat called fs.stat called immediate callback queued Loop 0 ends Loop 1 starts immediate callback gets called Loop 1 ends Loop 2 starts fs.stat completes, I/O callback queued fs.stat completes, I/O callback queued Loop 2 ends Loop 3 starts fs.stat I/O callback gets called fs.stat I/O callback gets called
其实没有人保证fs.stat 1在fs.stat2之前完成。 所以你发布的结果也可以
1 IMMEDIATE 2 LAST STAT 3 FIRST STAT
你可以做什么:
- 您可以使用fs.stat的同步版本。 但是,尽pipe使用起来很舒服,但会降低脚本的吞吐量,因为在fs.stat运行的时候您将阻止脚本的执行。 所以如果你不得不经常运行这部分代码,请使用以下方法之一!
- 您可能需要检查“ await ”以asynchronous运行代码,但要按顺序运行
- 如果完成顺序对您无关紧要,您也可以简单地使用Promise来包装这两个fs.stat调用。 然后就做一个Promise.all。 或者你可以使用asynchronous(一个库),提供了许多function来处理asynchronous性
- …
setImmediate
不会等待所有IO操作完成。 它只是优先考虑IO callback 。 当你在这里调用setImmediate
, fs.stat
调用还没有完成,因此它们的callbackfs.stat
还没有安排在事件循环中。