【问题标题】:Node.js read file using async/awaitNode.js 使用 async/await 读取文件
【发布时间】:2019-05-30 18:31:53
【问题描述】:

我正在尝试使用异步/等待代码来读取文件。 这是我的代码:

var fs = require('fs');

function readFile(fileName) {
  return new Promise(resolve => {
    //console.log(test);
    fs.readFile(fileName, 'utf8', function (err, data) {
      if (err) throw err;

      console.log(fileName)
      console.log(data)
    })
    resolve();
  });
}

async function run() {
  await readFile('file1.txt');
  await readFile('file2.txt');
  readFile('file3.txt');
}

run();

但结果仍然是随机的。这意味着 file3 有时会在 file2 之前读取。我哪里做错了?

【问题讨论】:

标签: node.js async-await


【解决方案1】:

有很多方法可以实现。

大部分在this link中都有解释


我会写一个简单的:

1) 使用util.promisify 将回调方法转换为promise:

const fs = require('fs');
const util = require('util');
const readFile = (fileName) => util.promisify(fs.readFile)(fileName, 'utf8');

(async () => {
  try {
    const files = ['file1.txt', 'file2.txt', 'file3.txt'];
    for (const file of files) {
      console.log(
        await readFile(file)
      );
    }
  }
  catch (error) {
    console.error(error);
  }
})();

2) *Sync 方法。由于您的代码不处理并发您可以使用*Sync 方法:

const fs = require('fs');

try {
  const files = ['file1.txt', 'file2.txt', 'file3.txt'];
  for (const file of files) {
    console.log(
      fs.readFileSync(file, 'utf8')
    );
  }
}
catch (error) {
  console.error(error);
}


顺便说一句。这是您的固定代码:

var fs = require('fs');

function readFile(fileName) {
  return new Promise((resolve, reject) => {
    fs.readFile(fileName, 'utf8', function (error, data) {
      if (error) return reject(error);

      console.log(fileName)
      console.log(data)

      resolve();
    })
  });
}

async function run() {
  await readFile('file1.txt');
  await readFile('file2.txt');
  await readFile('file3.txt');
}

run();

因为您正在调用 readFile 并以相同的异步序列解析它,所以它同时被调用,这是 race condition 的原因。

您必须等待回调处理然后解决它(在回调范围内)。

【讨论】:

  • 感谢您展示其他方法来实现我的目标...实际上还有一些额外的代码来处理数据。是的,代码通过将 resolve() 移动到 fs.readFile() 内部来工作。备选方案 2 更容易理解。
【解决方案2】:

本机节点功能有几个选项

A) 使用fs.promises API

您可以在导入别名fs.promises 时使用destructuring assignment,就像fs 一样

const { promises: fs } = require("fs");

(async () => {
    try {
        let file1 = await fs.readFile("file1.txt", "utf-8");
        let file2 = await fs.readFile("file2.txt", "utf-8");

    } catch (e) {
        console.log("e", e);
    }
})()

B) 与util.promisify API

const fsSync = require("fs");
const {promisify} = require("util")

const fs = {
  readdir: promisify(fsSync.readdir),
  readFile: promisify(fsSync.readFile),
  // etc
};

(async () => {
    try {
        let file1 = await fs.readFile("file1.txt", "utf-8");
        let file2 = await fs.readFile("file2.txt", "utf-8");

    } catch (e) {
        console.log("e", e);
    }
})()

进一步阅读

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-01-29
    • 1970-01-01
    • 2017-03-28
    • 2017-10-15
    • 2017-05-29
    • 2018-11-27
    • 2018-04-02
    相关资源
    最近更新 更多