在 Node 中使用 fs.readFile 串行读取文件?

Posted

技术标签:

【中文标题】在 Node 中使用 fs.readFile 串行读取文件?【英文标题】:Read files in series with fs.readFile in Node? 【发布时间】:2019-05-18 20:15:45 【问题描述】:

我将任意数量的文件路径作为字符串存储在数组中。

我需要依次读取这些文件(即在开始读取下一个文件之前完成读取一个文件),并在每个文件读取后输出文件长度。并在读完所有文件后,打印'done'

我只能使用fs.readFile 和本机javascript。不允许使用 fs.readFileSync 或任何其他模块。另外,我在 Node v6 上,所以我不能使用 async/await。

有什么方法可以按照约束来实现功能吗?

【问题讨论】:

是的,您需要使用一次读取的回调来知道何时开始下一次读取...... Promise(在这样一个古老的节点中可能需要一个库)将使它更容易跨度> @JaromandaX 是的,我认为这就是想法。但是如何在任意大小的数组上实现它呢? 我喜欢使用带有 promise 的数组 reduce 来完成此类任务——但这绝不是唯一的方法 medium.com/@ajmeyghani/… fs.readFileSync 的约束对于现实世界的问题似乎有点武断;这是作业吗? 【参考方案1】:

在 Node 中使用 fs.readFile 同步读取文件?

没有。

异步函数是异步的。

它们不能变成同步函数。

即使你可以使用await(你已经排除了),它仍然是异步的,只是语法允许你在更广泛的上下文中以同步 style 编写代码仍然异步。

大部分 JavaScript 都是异步的。拥抱它。精益使用 Promise。不要试图与之抗争。

我需要按顺序读取这些文件(即读完一个文件 在开始阅读下一个之前),并输出文件长度 每个文件读取后。并在阅读完所有文件后,打印 '完成'。

编写一个沿数组迭代的递归函数。读取文件后,根据您是在数组末尾还是现在,增加迭代器并递归或打印 done

【讨论】:

【参考方案2】:

尝试使用generators。 在示例代码中,将 acync 函数替换为读取文件。

// emulate async action
const stt = (resolve, str) => 
  setTimeout(
    () => 
      console.log(str);
      resolve(str);
    ,
    2000
  );

// Create array of functions that return Promise
const arrFunc = ['foo', 'bar', 'baz', 'qux']
  .reduce(
    (acc, str) => 
      acc.push(() => 
        return new Promise(resolve => 
          stt(resolve, str);
        );
      );
      return acc;
    , []
  );

function* generator() 
  for (let func of arrFunc) 
    yield func();
  


const iterator = generator();

function quasiCo(generator, value) 
  const next = generator.next();
  console.log(next);
  if (!next.done) 
    next.value.then(res => 
      quasiCo(generator, res);
    );
  


quasiCo(iterator);

【讨论】:

【参考方案3】:

您不需要任何花哨的东西,如 Promise、async/await、生成器来实现这一点。

function readAllFiles(list) 
  if(list.length == 0) return
  console.log('reading ', list[0])
  return fs.readFile(list[0], function (err, file) 
    if (err) console.error(err); // report the error and continue
    console.log('list[0] length:', file.length); // report the file length
    readAllFiles(list.slice(1, list.length))
  )


var l = ['1', 'foo', 'bar']

readAllFiles(l)

【讨论】:

顺便说一句,使用递归时,应始终记住堆栈不是无限的。如果您打算以这种方式处理长列表,则将嵌套的readAllFiles 包装在setTimeout/setImmediate 中会很有用。更多详情:***.com/questions/20936486/… @AlexPovar 这不会导致堆栈溢出错误,因为readAllFiles 不会自行调用。它由我们传递给fs.readFile 函数的回调调用。

以上是关于在 Node 中使用 fs.readFile 串行读取文件?的主要内容,如果未能解决你的问题,请参考以下文章

node.js 中 fs.createReadStream 与 fs.readFile 的优缺点是啥?

Node.JS:fs.readFile 在 Ubuntu 上不起作用

Node.js fs.readfile/异步文件访问:在回调中获取当前文件

HTTP 状态代码 200 但页面未加载 Node.js Socket.io -- 使用 Socket.io 的 Node.js 教程,Daniel Nill,fs.readFile(),socket

[Node.js] Read a File in Node.js with fs.readFile and fs.readFileSync

node 基础API(fs)