createreadstream是异步的吗?

时间:2015-05-22 00:58:58

标签: node.js

https://nodejs.org/api/fs.html#fs_fs_createreadstream_path_options。 我也有一个普遍的问题。

我可以假设,除非文档中另有说明,否则提到的任何功能都是异步的?

1 个答案:

答案 0 :(得分:13)

  

createreadstream是异步的吗?

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

以下是fs.createReadStream()的签名:

fs.createReadStream(path[, options])

而且,在options对象中,没有回调选项,也没有提到返回的promise。这不是典型的异步接口。

另一方面,如果你看一下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()是一个具有完成事件的异步操作。但是,由于它与从文件读取相结合的方式,你通常不必像使用异步一样使用它,因为它的异步行为与文件的异步读取相结合。