2017-02-15 86 views
0

对代码为什么在文件读取回调之前调用setImmediate?

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

回答

0

为什么你期望fs.readFile()完成不到一个滴答?特别是对于fs.readFile(),会发生多种操作:打开文件,读取一个或多个块并关闭文件。这些操作需要相当长的时间(相对来说),并且可以在调用fs.readFile()回调之前轻松地采用多个事件循环。

+0

正如我所提到的,setImmediate计划的回调应该在事件循环结束时运行,这意味着所有事情都必须在setImmediate回调被触发之前完成,这就是nodejs官方文档告诉的。因此,无论特定事件循环中的任何代码是否被占用,都无关紧要。 – nurulnabi

+0

'setImmediate()'回调函数在事件循环的下一个tick的*开头执行(在针对事件循环的当前tick执行I/O回调之后)。但是,正如我所说的那样,打开文件,读取整个文件,关闭文件等所有系统调用都将立即*完成,以至于它们的回调将在当前刻度结束时执行。事实上,我认为这可能是不可能的,因为异步本质(每个操作都不能并行执行,所以它们是以串行方式执行的)。 – mscdex

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超过了明显的原因,因为它在 someAsyncOperation()

0等待100毫秒

setImmediate()后,它会返回给回调函数,因为没有其他 fd是现在可以被执行。回调函数现在打印出 适当的值delay

并且程序结束。

+0

_在I/O事件的回调之后和使用setTimeout()和setInterval()创建的定时器被触发之前,调度回调的“立即”执行._这是我从你给出的链接中获得的行,但是我的代码的行为是与我刚刚提到的相反。 – nurulnabi

+0

根据你的代码我已经改进了答案,希望现在可以帮助! –

1

当程序开始执行,

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

当程序完成执行后,它进入事件循环。它检查哪些I/O回调正在等待。

  1. 现在,fs.readFile进入图片。但它需要一个文件来阅读。因此,它在操作系统内核中保留fd(文件描述符),并说'让我知道文件何时准备好读取'[仅仅是为了您的理解,它并不真正说出该行],并且甚至没有等待1纳米第二。
  2. 现在下一个setImmediate将开始执行。
  3. 在事件循环中将文件打开为fs.readFile后,操作系统将返回fdfs.readFile现在就完成了。

所以,setImmediate首先完成比fs.readFile

+0

据我所知,在fs.readFile中提供的回调将不会被安排在事件回调队列中执行,直到fs.readFile成功/不成功读取文件,那么只有回调将被安排执行,并且自从在包括I/O在内的所有回调(正如文档中提到的)已经返回之后,setImmediate回调必须被调用。 – nurulnabi

+0

'fs.readFile(file [,options],callback') 'file' | | 文件名或文件描述符。 '异步读取文件的全部内容':含义=>它在循环中排队,因为没有其他线程在后台并行运行它。只有现在可以做的事情是将'fd'提供给内核。一旦发生这种情况,它会再次回到循环,但它已经出队一次,现在机会被赋予循环中的下一项,在你的情况下是'setImmediate'。当它被再次调用时,循环中的下一项开始执行,即'fs.readFile'。 –

相关问题