非同期でファイルを読み取る方法/適切に待つ?


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コンソールが表示されます。


これはあなたの質問に答えますか?node.jsでファイルシステムをasync / awaitで使用する
KyleMit

回答:


165

await/ を使用asyncするには、promiseを返すメソッドが必要です。コア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をラップする必要があることを知りませんでした。あなたは素晴らしいです。
Jeremy Dicaire、2017年

4
コアAPIは、最新のPromise仕様とasync/ の採用よりも古いawaitため、これは必要なステップです。良いニュースはpromisify、通常、混乱なく機能することです。
tadman 2017年

1
これは、FSでasync-awaitを通常は利用できないという混乱を処理します。これありがとう!あなたは私を1トン救った!あなたのようにこれに本当に対処する答えはありません。
jacobhobson

3
また、awaitは推測できるため、冗長です。例で明示的に待機させたい場合にのみ、行うことができますconst file = await readFile...; return file;
bigkahunaburger

1
@shijin NodeコアAPIがpromiseに切り替わるまでは、現時点ではありそうもありませんが、そうです。ただし、それを行うNPMラッパーがあります。
tadman

149

Node v11.0.0のfs promiseはネイティブで利用可能ですpromisify

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

4
いいえ、クリーンでシンプルな追加LIBS -このべき望ましい答え
アダムBubela

2
2019年10月21日の時点で、v12はアクティブなLTSバージョンです
cbronson

16
import { promises as fs } from "fs";インポート構文を使用する場合。
tr3online

21

これは@Joelの回答のTypeScriptバージョンです。Node 11.0以降で使用できます。

import { promises as fs } from 'fs';

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

18

readFileコマンドは、次のようなpromiseで簡単にラップできます。

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

async関数内でawaitが使用されていませんか?
VikasBhat

@VikasBhatはい、仕様ではそうする必要があるため、上のawait行は別の非同期関数内で使用されます。
whoshotdk

8

fs.promisesNode 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

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.