2015-05-22 71 views

回答

8

是createreadstream异步吗?

是和否。这个问题实际上更多的是语义问题,因为它隐藏了一个异步操作下的同步外观界面。 fs.createReadStream()似乎有一个同步接口。它不返回承诺或接受回调,以便在完成时返回或发回一些结果。所以,它从界面看起来是同步的。而且,我们知道从使用它开始使用流时不需要等待。所以,你使用它就好像它是一个同步接口。

这里的签名fs.createReadStream()

fs.createReadStream(path[, options]) 

而且,在选择对象,没有回调选项,并没有提到返回的承诺。这不是一个典型的异步接口。


上如果你看的fs.rename()签名另一方面:

fs.rename(oldPath, newPath, callback) 

你看,它需要的是在文档被称为“完成回调”的回调。这个功能显然是异步的。


但是,fs.createReadStream()确实打开一个文件,并将其以异步方式打开该文件,不会禁止。

如果您想知道fs.createReadStream()在需要异步打开文件时如何同步,这是因为fs.createReadStream()在返回时尚未打开该文件。

正常使用流时,您可以立即开始从流中读取数据。但是,在流的内部,如果文件尚未打开,它将等到文件完成打开后再实际尝试读取文件。因此,打开文件的过程对流的用户是隐藏的(这通常是件好事)。

如果您想知道实际完成的文件何时打开,那么流中会有一个open事件。而且,如果打开该文件时出现错误,则会在该流上发生error事件。所以,如果你想获得技术,你可以说fs.readStream()实际上是一个异步操作,异步操作的完成通过openerror事件进行通信。

let rstream = fs.createReadStream("temp.txt"); 
rstream.on('open', (fd) => { 
    // file opened now 
}); 
rstream.on('error', (err) => { 
    // error on the stream 
}); 

但是,在fs.createReadStream()正常使用时,程序员不必因为它是对用户隐藏当流从下一个自动读取处理监视文件打开事件。当您创建一个读取流并立即要求从它读取(这是一个异步接口)时,在内部流对象等待文件完成打开,然后读取一些字节,等待文件读取完成,然后通知完成读取操作。因此,他们只是将文件打开完成与第一次读取结合起来,从而使程序员在发出第一次读取操作之前,还有一个等待文件打开的额外步骤。

因此,从技术上来说fs.createReadStream()是一个具有完成事件的异步操作。但是,由于它与文件读取相结合的方式,通常不必像使用异步一样使用它,因为它的异步行为与来自文件的异步读取相结合。

+0

什么时候在'createReadStream'中实际打开文件?你提到“以后某个时候”,但是什么时候完成了? – jmq

+0

@jmq - 如果你看[源代码](https://github.com/nodejs/node/blob/master/lib/fs.js#L1678),你可以看到'fs.createReadStream()'创建在构造函数中调用'this.open()'的'ReadStream'对象。但是,这是异步的,因此它会在'fs.createReadStream()'返回后的某个时候完成。流上的其他方法检查文件是否完成了打开,如果没有,他们注册一个事件处理程序,在打开完成时通知它们并在打开完成后执行它们的工作。这可以工作,因为一切都是异步的。 – jfriend00

+0

@jmq - 如果您想知道何时“open”完成,您可以自己为流上的'open'事件注册事件侦听器。 – jfriend00