0

看看这些代码行

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 回调执行背后的逻辑是什么。

4

3 回答 3

1

当程序开始执行时,

  1. setImmediate将进入事件循环。
  2. 接下来,fs.readFile也进入事件循环。

当程序完成执行时,它会进入事件循环。它检查哪些 I/O 回调待处理。

  1. 现在,fs.readFile进入画面。但它需要一个文件来读取。所以它fd在操作系统内核中保留一个(文件描述符)并说“让我知道文件何时可以读取”[只是为了您的理解,它并没有真正说那行]并且甚至没有等待 1 纳秒就回来了.
  2. 现在下一个setImmediate将开始执行。
  3. 操作系统将fd在打开文件到fs.readFile事件循环后返回。fs.readFile现在将完成。

所以,setImmediate比先完成fs.readFile

.

于 2017-02-15T12:42:30.930 回答
0

为什么你会期望fs.readFile()在不到一秒的时间内完成?尤其是fs.readFile()有多个操作发生:打开文件,读取一个或多个块,关闭文件。这些操作需要相当长的时间(相对而言),并且在fs.readFile()调用回调之前很容易花费一个以上的事件循环滴答声。

于 2017-02-15T10:19:35.643 回答
0

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

每当setImmediate()被调用时,它都会返回到事件循环(也称为 uv_loop),以便执行其他排队等待执行的函数。

你也可以通过这个链接:setImmediate function

在您的代码中,

第 1 步,您正在调用someAsyncOperation ()同步工作,只需打印并在循环中等待 100 毫秒。

第 2 步,timeoutScheduled 分配Date.now()

再次调用第 3 步,someAsyncOperation ()它再次执行相同的操作(类似于第 1 步)

第4步,它得到一个I/O操作,即fs.readFile,遇到这行代码后,它setImmediate()运行函数,现在delay = Date.now() - timeoutScheduled(延迟将保持一个大于100的值,原因很明显,因为它在等待100毫秒 someAsyncOperation ()

之后setImmediate(),它返回到回调函数,因为 fd现在没有其他准备好执行。回调函数现在打印适当的delay

程序结束。

于 2017-02-15T11:20:09.770 回答