async function* readChunkIter(chunksAsync) {
for await (const chunk of chunksAsync) {
// magic
yield chunk;
}
}
const fileStream = fs.createReadStream(filePath, { highWaterMark: 1024 * 64 });
const readChunk = readChunkIter(fileStream);
function* readChunkIter(fd) {
// loop
// magic
fs.readSync(fd, buffer, 0, chunkSize, bytesRead);
yield buffer;
}
const fd = fs.openSync(filePath, 'r');
const readChunk = readChunkIter(fd);
最好与生成器函数一起使用,为什么?
更新:我不是在寻找更好的方法,我想知道使用这些功能之间的区别
答案 0 :(得分:0)
首先,您将比较同步文件操作fs.readSync()
与流中的异步文件操作(内部使用fs.read()
)。因此,这有点像供服务器使用的苹果和橙子。
如果这是在服务器上,则不要在服务器启动时使用同步文件I / O,因为在处理请求或任何其他服务器事件时,同步文件I / O会在文件读取操作期间阻塞整个事件循环,这会极大地影响降低服务器的可伸缩性。仅使用异步文件I / O,这两种情况之间将是流。
否则,如果它不在服务器上或不在意在同步文件操作期间阻止node.js事件循环的任何进程上,则完全由您决定使用哪种接口。
其他评论:
也不清楚为什么将for await()
包装在生成器中。调用者可以自己使用for await()
并避免将其包装在生成器中。
用于读取文件的流通常以事件驱动的方式使用,方法是将事件侦听器添加到data
事件并在数据到达时对其进行响应。如果您只是要异步读取文件中的数据块,那么流实际上没有任何好处。您也可以只使用fs.read()
或fs.promises.read()
。
我们无法真正地以最佳/更好的方式来解决问题,而没有看到您要为其编写代码的整体问题。您刚刚显示了一个读取数据的小片段。最好的结构化方法取决于高层代码如何最方便地使用/使用数据(您未显示)。
我真的没有问正确的问题。我不是在寻找更好的方法,我想知道使用这些功能之间的区别。
好吧,主要区别在于fs.readSync()
处于阻塞和同步状态,因此阻塞了事件循环,从而破坏了服务器的可伸缩性,因此在服务器环境中(在启动代码期间除外)不应使用。 node.js中的流是异步的,不会阻塞事件循环。
除了这种区别之外,流是比直接读取文件更高级别的构造,并且在您实际使用流的功能时应使用它,而在从文件中读取块时可能不应该使用它直接并且不使用流的任何功能。
特别是,对于流,错误处理并不总是那么清晰,尤其是在尝试对流使用await
和promises时。这可能是因为读取流最初被设计为事件驱动的对象,并且这意味着在error
事件上间接传递错误,这会使直接读取操作中的错误处理变得复杂。如果您不使用读取流的事件驱动性质或流的某些转换功能或其他主要功能,则不使用它们-我将使用更传统的fs.promises.readFile()
来读取数据。>