web-dev-qa-db-ja.com

node.jsのファイルシステムをasync / awaitで使用する

いくつかのファイルシステム操作でasync/awaitを使いたいのですが。私はbabel-plugin-syntax-async-functionsを使っているので、通常async/awaitはうまく動きます。

しかし、このコードで私はnamesが未定義の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();

私がコードをコールバック地獄バージョンに再構築するとき、すべては問題ないですそして私はファイル名を取得します。あなたのヒントをありがとう。

68
Quellenangeber

ノード8.0.0以降では、これを使用できます。

import fs from 'fs';
import {promisify} from 'util';

const readdir = promisify(fs.readdir);

async function myF() {
  let names;
  try {
    {err, names} = await readdir('path/to/dir');
    if (err) {
        // Handle the error.
    }
  } catch (e) {
    console.log('e', e);
  }
  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 をご覧ください。

85
Azbykov

Node.js 8.0.0

ネイティブの非同期/待機

約束する

このバージョンから、tilライブラリのネイティブ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を使用してください。

40
dimpiax

File-Api fs.readdirは約束を返さないため、間違った動作をする可能性があります。それはコールバックだけを取ります。 async-awaitの構文を使いたいのであれば、このような機能を「約束」することができます。

function readdirAsync(path) {
  return new Promise(function (resolve, reject) {
    fs.readdir(path, function (error, result) {
      if (error) {
        reject(error);
      } else {
        resolve(result);
      }
    });
  });
}

代わりにそれを呼び出します。

names = await readdirAsync('path/to/dir');
32
wursttheke

ネイティブ非同期はバージョン11以降のスタイルfs関数を待ちます

Node.JS 11.0.0(安定版)、およびバージョン10.0.0(実験的)以降は、既に確認されているファイルシステムメソッドにアクセスでき、コールバックの戻り値を確認するのではなくtry catch例外処理を使用して使用できますエラーが含まれています。

APIはとてもきれいでエレガントです! fsオブジェクトの.promisesメンバーを使用するだけです。

import fs from 'fs';
const fsPromises = fs.promises;

async function listDir() {
  try {
    return await fsPromises.readdir('path/to/dir');
  } catch (err) {
    console.error('Error occured while reading directory!', err);
  }
}

listDir();
15
bman

これは私のために働いたものです:

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で機能します:node --harmony my-script.js。そしてノード7.7から始まって、 あなたはこのフラグさえ必要としません

冒頭に含まれている fsp ライブラリーは、fs(および fs-ext )の単なるラッパーです。

最近私はあなたがばかにならずにnodeでできることについて本当に去りました!ネイティブのasync/awaitは、コードを書くのをとても楽しいものにします。

更新2017-06:fs-promiseモジュールは廃止予定です。同じAPIで代わりに fs-extra を使用してください。

5

カスタム関数と比較して、 https://github.com/davetemplin/async-file などのnpmパッケージを使用することをお勧めします。例えば:

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');

他の回答は古くなっています

4
sean2078

私はエクスポートするこの小さな助けモジュールを持っています 約束された バージョンのfs関数

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

module.exports = {
  readdir: promisify(fs.readdir),
  readFile: promisify(fs.readFile),
  writeFile: promisify(fs.writeFile)
  // etc...
};
1
grigson