Bagaimana cara membaca file dengan async / await dengan benar?

120

Saya tidak tahu bagaimana async/ awaitbekerja. Saya sedikit mengerti tapi saya tidak bisa membuatnya bekerja.

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

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

Saya tahu saya bisa menggunakan readFileSync, tetapi jika saya melakukannya, saya tahu saya tidak akan pernah mengerti async/ awaitdan saya akan mengubur masalahnya.

Sasaran: Memanggil loadMonoCounter()dan mengembalikan konten file.

File itu bertambah setiap kali incrementMonoCounter()dipanggil (setiap pemuatan halaman). File tersebut berisi dump buffer dalam biner dan disimpan di SSD.

Apa pun yang saya lakukan, saya mendapatkan kesalahan atau undefineddi konsol.

Jeremy Dicaire
sumber
Apakah ini menjawab pertanyaan Anda? Menggunakan filesystem di node.js dengan async / await
KyleMit

Jawaban:

165

Untuk menggunakan await/ asyncAnda membutuhkan metode yang mengembalikan promise. Fungsi API inti tidak melakukannya tanpa pembungkus seperti 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);
})

Sebagai catatan, readFileSynctidak menerima panggilan balik, itu mengembalikan data atau melontarkan pengecualian. Anda tidak mendapatkan nilai yang Anda inginkan karena fungsi yang Anda berikan diabaikan dan Anda tidak menangkap nilai pengembalian yang sebenarnya.

anak laki-laki
sumber
3
Terima kasih, saya tidak tahu bahwa saya perlu membungkus API inti. Kamu Menakjubkan.
Jeremy Dicaire
4
API inti lebih dulu menentukan spesifikasi Promise modern dan penerapan async/ await, jadi itu adalah langkah yang perlu. Kabar baiknya promisifybiasanya membuatnya bekerja tanpa kekacauan.
tadman
1
Ini menangani kekacauan karena tidak dapat memanfaatkan async-await dengan FS secara normal. Terima kasih untuk ini! Anda menyelamatkan saya satu ton! Tidak ada jawaban yang benar-benar menjawab ini seperti jawaban Anda.
jacobhobson
3
Juga menunggu agak berlebihan karena bisa disimpulkan. Hanya jika Anda ingin secara eksplisit memiliki await misalnya, Anda dapat melakukannya const file = await readFile...; return file;.
bigkahunaburger
1
@shijin Hingga API inti Node beralih ke promise, yang kemungkinannya kecil pada saat ini, ya. Ada pembungkus NPM yang melakukannya untuk Anda.
tadman
150

Karena janji Node v11.0.0 fs tersedia secara native tanpa promisify:

const fs = require('fs').promises;
async function loadMonoCounter() {
    const data = await fs.readFile("monolitic.txt", "binary");
    return new Buffer(data);
}
Joel
sumber
4
tidak ada lib tambahan, bersih dan sederhana - ini harus jawaban yang lebih disukai
Adam Bubela
2
Mulai 21-Okt-2019, v12 adalah versi LTS aktif
cbronson
16
import { promises as fs } from "fs";jika Anda ingin menggunakan sintaks impor.
tr3online
21

Ini adalah versi TypeScript dari jawaban @ Joel. Ini dapat digunakan setelah Node 11.0:

import { promises as fs } from 'fs';

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

Anda dapat dengan mudah menggabungkan perintah readFile dengan janji seperti ini:

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

lalu gunakan:

await readFile("path/to/file");
Shlomi Schwartz
sumber
Bukankah await digunakan di dalam fungsi async?
VikasBhat
@VikasBhat Ya, baris await di atas akan digunakan di dalam fungsi asinkron lain karena spesifikasi mengharuskannya demikian.
whoshotdk
8

Anda dapat menggunakan fs.promisestersedia secara native sejak 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)
  }
}
arnaudjnn
sumber
Jika Anda hanya ingin menggunakan const fs = require('fs').promises
promise
1

Ada fs.readFileSync( path, options )metode yang sinkron.

George Ogden
sumber