Node.js 为什么在文件读取回调之前调用此setImmediate?

Node.js 为什么在文件读取回调之前调用此setImmediate?,node.js,callback,setimmediate,Node.js,Callback,Setimmediate,看看这些代码行 function someAsyncOperation () { console.log("inside someAsyncOperation"); var startCallback = Date.now(); // do something that will take 10ms... while (Date.now() - startCallback <= 100) { ; // do nothing } } someAsyncOpera

看看这些代码行

function someAsyncOperation () {
  console.log("inside someAsyncOperation");
  var startCallback = Date.now();
  // do something that will take 10ms...
  while (Date.now() - startCallback <= 100) {
    ; // do nothing
  }
}

someAsyncOperation();

var timeoutScheduled = Date.now();

setImmediate(function () {
  var delay = Date.now() - timeoutScheduled;
  console.log(delay + "ms have passed since I was scheduled");
});


someAsyncOperation();
fs.readFile("./noor.txt",function(err,data){
    var delay = Date.now() - timeoutScheduled;
    console.log(delay + "file read");
});
正如我所知,setImmediate回调是在任何I/O操作之后在事件循环的末尾运行的。但在我的例子中,setImmediate回调是在文件读取操作返回之前调用的。请解释为什么会发生这种情况,或者setImmediate回调执行背后的逻辑是什么。

为什么您希望fs.readFile在不到一个刻度的时间内完成?尤其是对于fs.readFile,会发生多个操作:打开文件、读取一个或多个块以及关闭文件。相对而言,这些操作需要相当长的时间,并且在调用fs.readFile回调之前可以轻松地执行多个事件循环。

调用setImmediate函数以停止当前正在执行的函数的执行,并调用另一个函数以停止饥饿。它主要在I/O操作时调用,以停止此函数,从而消耗在NodeJs异步调用中实现的cpu时间,因为它是单线程的。 因此,它有助于无延迟地执行回调函数

无论何时调用setImmediate,它都会返回到事件循环(也称为uv_循环),以便执行等待执行的其他排队函数

您也可以通过此链接:

在代码中

步骤1,您正在调用正在工作的someAsyncOperation 同步地,只需打印并在循环中等待100毫秒

步骤2,timeoutScheduled分配日期。现在

第3步,再次调用someAsyncOperation,该操作再次执行相同的操作 与步骤1相似的事情

第四步,它得到了一个I/O操作,即fs.readFile,遇到这行代码后,它转到setImmediate函数, now delay=Date.now-timeoutScheduled delay将保留一个值 超过100,原因很明显,因为它等待100毫秒的时间 异步操作

setImmediate之后,它将返回回调函数,而不是其他函数 fd现在可以执行了。回调函数现在打印 适当的延迟值

节目结束了


当程序开始执行时

setImmediate将进入事件循环。 接下来,fs.readFile也进入事件循环。 当程序完成执行后,它进入事件循环。它检查哪些I/O回调处于挂起状态

现在,fs.readFile出现在图片中。但它需要一个文件来读取。因此,它在操作系统内核中保留了一个fdfile描述符,并说“当文件准备好读取时通知我”[仅供您理解,它实际上没有说这一行],然后返回,甚至不需要等待1纳秒。 现在,下一个setImmediate将开始执行。 在事件循环中将文件打开到fs.readFile后,操作系统将返回fd。fs.readFile将立即完成。 因此,setImmediate比fs.readFile先完成


.

计划在I/O事件回调之后以及使用setTimeout和setInterval创建的计时器触发之前立即执行回调。这是我从你给出的链接中得到的一行,但是我的代码的行为与我提到的正好相反。我已经根据你的代码改进了答案,希望现在能有所帮助!正如我提到的,setImmediate计划的回调应该在事件循环结束时运行,这意味着在触发setImmediate回调之前必须完成所有工作,这是nodejs官方文档告诉我们的。因此,该特定事件循环中的任何代码段占用的时间都无关紧要。setImmediate回调在对事件循环的当前勾号执行I/O回调后,在事件循环的下一个勾号开始时执行。但是,正如我所说的,打开一个文件、读取整个文件和关闭文件所需的所有系统调用都不可能立即完成,因此它们的回调将在当前勾号结束时执行。事实上,我想说这可能是不可能的,因为每个操作都是异步的,不能并行执行,就我所知,fs.readFile中提供的回调不会安排在事件回调队列中执行,直到fs.readFile成功/未成功读取文件,然后才会安排执行回调,因为毕竟必须调用setImmediate回调包括官方文档中提到的I/O在内的回调已返回.fs.readFilefile[,options],回调文件| | filename或文件描述符。异步读取文件的全部内容:means=>它在循环中排队,因为没有其他线程在后台并行运行它。现在唯一可以做的就是将fd提供给内核。一旦发生这种情况,它会再次返回循环,但它已经退出一次队列,现在机会是giv en到循环中的下一项,在您的情况下,该项设置为立即。当调用此函数时,循环中的下一项开始执行,即fs.readFile。