如何正确地使用async / await读取文件?


120

我无法弄清楚async/的await运作方式。我有点理解,但无法使其正常工作。

function loadMonoCounter() {
    fs.readFileSync("monolitic.txt", "binary", async function(err, data) {
       return await new Buffer( data);
  });
}

module.exports.read = function() {
  console.log(loadMonoCounter());
};

我知道我可以使用readFileSync,但如果这样做,我知道我永远不会理解async/ await我只会埋葬这个问题。

目标:调用loadMonoCounter()并返回文件的内容。

该文件在每次incrementMonoCounter()调用时都会递增(每次加载页面)。该文件包含二进制缓冲区的转储,并存储在SSD中。

无论我做什么,都会出现错误或undefined在控制台中。


Answers:


165

要使用await/,async您需要返回承诺的方法。没有包装器,核心API函数就不会这样做promisify

const fs = require('fs');
const util = require('util');

// Convert fs.readFile into Promise version of same    
const readFile = util.promisify(fs.readFile);

function getStuff() {
  return readFile('test');
}

// Can't use `await` outside of an async function so you need to chain
// with then()
getStuff().then(data => {
  console.log(data);
})

注意,readFileSync不进行回调,而是返回数据或引发异常。您没有得到想要的值,因为您提供的函数将被忽略,并且您没有捕获实际的返回值。


3
谢谢,我不知道我需要包装核心API。你真棒。
杰里米·迪卡

4
核心API早于现代Promise规范和async/ 的采用await,因此这是必要的步骤。好消息promisify通常是使其正常工作。
tadman

1
这处理了无法正常使用FS的async-await的麻烦。这次真是万分感谢!你救了我一吨!没有答案能像您一样真正解决这个问题。
jacobhobson

3
另外,等待可以有点多余,因为可以推断出来。仅当您确实想在示例中明确地等待时,才可以这样做const file = await readFile...; return file;
bigkahunaburger

1
@shijin,直到Node核心API转换为promise,这在目前是不可能的,然后是。不过,有NPM包装器可以为您完成此任务。
tadman '19

150

由于Node v11.0.0 fs promises本身就可以使用,而无需promisify

const fs = require('fs').promises;
async function loadMonoCounter() {
    const data = await fs.readFile("monolitic.txt", "binary");
    return new Buffer(data);
}

4
没有其他库,干净且简单-这应该是更可取的答案
Adam Bubela

2
作为21-OCT-2019,V12是一个活跃的LTS版本
cbronson

16
import { promises as fs } from "fs";如果要使用导入语法。
tr3online

21

这是@Joel答案的TypeScript版本。在节点11.0之后可用:

import { promises as fs } from 'fs';

async function loadMonoCounter() {
    const data = await fs.readFile('monolitic.txt', 'binary');
    return Buffer.from(data);
}

18

您可以像这样用promise轻松包装readFile命令:

async function readFile(path) {
    return new Promise((resolve, reject) => {
      fs.readFile(path, 'utf8', function (err, data) {
        if (err) {
          reject(err);
        }
        resolve(data);
      });
    });
  }

然后使用:

await readFile("path/to/file");

在异步函数中不使用吗?
VikasBhat

@VikasBhat是的,根据规范要求,上面的await行将在另一个异步函数中使用。
whoshotdk

8

您可以fs.promises从Node v11.0.0开始使用本机可用

import fs from 'fs';

const readFile = async filePath => {
  try {
    const data = await fs.promises.readFile(filePath, 'utf8')
    return data
  }
  catch(err) {
    console.log(err)
  }
}

如果您只想使用承诺,则可以执行以下操作const fs = require('fs').promises
nathanfranke

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.