2015-08-13 21 views
2
"use strict" 

const 
    fs = require('fs'), 
    stream = fs.createReadStream("file.txt"), 
    timeout = 0; 

stream.on('data', function() { 
    console.log("File Read"); 
}); 

setTimeout(function(){ 
    console.log("setTimeout : " + timeout); 
}, timeout); 

我学习的Node.js/JavaScript的,我想知道这是为什么程序返回回调队列顺序

setTimeout : 0 
File Read 

,而不是周围的其他方法。

纠正我,如果我错了,但在javascript回调队列是先进先出,首先堆积stream

我认为由于的nodejs非阻挡性质,既回调在“平行”和第一setTimeout饰面和返回(例如1000毫秒的超时将切换的结果。)

回答

4

运行如果我错了,请纠正我,但在JavaScript中,回调队列是fifo, 首先将流首先堆叠出来?

不完全。异步回调处理FIFO的顺序,他们完成他们的操作,而不是在他们的操作启动的顺序。因此,操作完成所需的时间对于确定回调计划的时间非常重要。短操作可能在长时间操作之前完成,即使它们稍后启动。

这需要时间来打开文件,并开始读它,所以它首先出现setTimeout()不花时间。当你有独立的异步操作时,你几乎不会“知道”它们会以什么顺序出现,因为它取决于各种函数的内部时序。计时器被启动之前

的readStream操作得到启动,但计时器结束readStream操作获取其第一个数据之前,只是由于工作的两个异步操作内部所需的量。

我认为由于的NodeJS的非阻塞性质,既 回调在“平行”运行和的setTimeout完成第一和 返回(例如1000毫秒的超时将切换的结果。)

是的,这是正确的。


想想这样吧。你有两个强大的扩音器和一个非常好的麦克风。您设置了两个目标,将扩音器指向并监听返回的回声。一个目标即非常近,一个目标非常远。您首先在距离较远的目标处爆炸扩音器,然后立即在靠近目标处爆炸扩音器。在毫不奇怪,你从近距离目标回波第一,即使你派出了爆炸后的第一个,只是因为从远处目标回波花费很多时间来遍历所有额外的距离和送还给你。你的readStream也是如此。即使你第一次启动它,它需要比setTimeout(fn, 0)所以setTimeout()结束第一长很多,因此首先调用它的回调。


如果定时对你很重要,那么你应该使用工具,如承诺明确的排序操作异步还是等到所有必要的结果准备就绪。一个好的设计不应该“假设”一个异步操作会在另一个之前完成,除非你的代码专门确保通过对操作进行排序。

0

令人惊讶的是,我做了一个视频教程解释这个概念2天前,你问了这个。 Do watch this 9 min video to get a good understanding of this.这是解释。在Nodejs和JS中有一个叫做Eventloop的概念。 Eventloop的功能是监视正在运行的代码和堆栈上的代码。正如你所说的,从代码块被推入堆栈的是一个FIFO。但是,如果有任何异步或回调方法或必须执行的操作,则Eventloop会跳转到执行操作来处理这些操作。什么eventloop基本上做8s,它有一个自己的队列,它维护这些回调方法。当堆栈空闲时,队列中的这段代码被放入堆栈并执行。

0

这纯粹是因为节点js的IO非阻塞功能。您的文件读取操作是IO事件,因此它将被推送到事件队列,setTimeOut函数将立即执行。一旦文件读取完成,使用它的回调,它将加入主控制流程。因此,setTimeOut将首先执行,然后执行File读取。简单。