我想在一些文件系统操作中使用async/await。通常async/await工作正常,因为我使用babel-plugin-syntax-async-functions。

但在这段代码中,我遇到了name未定义的if情况:

import fs from 'fs';

async function myF() {
  let names;
  try {
    names = await fs.readdir('path/to/dir');
  } catch (e) {
    console.log('e', e);
  }
  if (names === undefined) {
    console.log('undefined');
  } else {
    console.log('First Name', names[0]);
  }
}

myF();

当我将代码重建为回调地狱版本时,一切都OK,我得到了文件名。 谢谢你的提示。


当前回答

与自定义函数相比,建议使用npm包,例如https://github.com/davetemplin/async-file。例如:

import * as fs from 'async-file';

await fs.rename('/tmp/hello', '/tmp/world');
await fs.appendFile('message.txt', 'data to append');
await fs.access('/etc/passd', fs.constants.R_OK | fs.constants.W_OK);

var stats = await fs.stat('/tmp/hello', '/tmp/world');

其他答案都过时了

其他回答

Node.js 8.0.0

本机异步/等待

Promisify

从这个版本开始,你可以使用来自util库的原生Node.js函数。

const fs = require('fs')
const { promisify } = require('util')

const readFileAsync = promisify(fs.readFile)
const writeFileAsync = promisify(fs.writeFile)

const run = async () => {
  const res = await readFileAsync('./data.json')
  console.log(res)
}

run()


保证包装

const fs = require('fs')

const readFile = (path, opts = 'utf8') =>
  new Promise((resolve, reject) => {
    fs.readFile(path, opts, (err, data) => {
      if (err) reject(err)
      else resolve(data)
    })
  })

const writeFile = (path, data, opts = 'utf8') =>
  new Promise((resolve, reject) => {
    fs.writeFile(path, data, opts, (err) => {
      if (err) reject(err)
      else resolve()
    })
  })

module.exports = {
  readFile,
  writeFile
}

...


// in some file, with imported functions above
// in async block
const run = async () => {
  const res = await readFile('./data.json')
  console.log(res)
}

run()

建议

如果你不想在等待块上重新抛出异常,总是使用try..catch。

从v10.0开始,您可以使用fs。承诺

使用readdir的示例

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

async function myF() {
    let names;
    try {
        names = await fs.readdir("path/to/dir");
    } catch (e) {
        console.log("e", e);
    }
    if (names === undefined) {
        console.log("undefined");
    } else {
        console.log("First Name", names[0]);
    }
}

myF();

使用readFile的示例

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

async function getContent(filePath, encoding = "utf-8") {
    if (!filePath) {
        throw new Error("filePath required");
    }

    return fs.readFile(filePath, { encoding });
}

(async () => {
    const content = await getContent("./package.json");

    console.log(content);
})();

与自定义函数相比,建议使用npm包,例如https://github.com/davetemplin/async-file。例如:

import * as fs from 'async-file';

await fs.rename('/tmp/hello', '/tmp/world');
await fs.appendFile('message.txt', 'data to append');
await fs.access('/etc/passd', fs.constants.R_OK | fs.constants.W_OK);

var stats = await fs.stat('/tmp/hello', '/tmp/world');

其他答案都过时了

从8.0.0节点开始,你可以使用这个:

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

const readdir = util.promisify(fs.readdir);

async function myF() {
  let names;
  try {
    names = await readdir('path/to/dir');
  } catch (err) {
    console.log(err);
  }
  if (names === undefined) {
    console.log('undefined');
  } else {
    console.log('First Name', names[0]);
  }
}

myF();

看到https://nodejs.org/dist/latest-v8.x/docs/api/util.html util_util_promisify_original

以下是对我有效的方法:

const fsp = require('fs-promise');

(async () => {
  try {
    const names = await fsp.readdir('path/to/dir');
    console.log(names[0]);
  } catch (e) {
    console.log('error: ', e);
  }
})();

当和谐标志被启用时,这段代码可以在没有babel的节点7.6中工作:从节点7.7开始,您甚至不需要这个标志!

开头包含的fsp库只是fs(和fs-ext)的约定包装器。

这些天你可以在没有babel的节点上做什么,我真的很兴奋!原生异步/await使编写代码变得如此愉快!

UPDATE 2017-06: fs-promise模块已弃用。使用fs-extra代替相同的API。