wake-up-neo.com

Dateisystem in node.js mit async/await verwenden

Ich möchte async/await bei einigen Dateisystemvorgängen verwenden. Normalerweise funktioniert async/await gut, da ich babel-plugin-syntax-async-functions verwende.

Aber mit diesem Code stoße ich in den Falls-Fall, in dem names nicht definiert ist:

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

Wenn ich den Code in die Callback-Höllenversion umwandle, ist alles in Ordnung und ich bekomme die Dateinamen.

45
Quellenangeber

Ab Knoten 8.0.0 können Sie Folgendes verwenden:

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

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

68
Azbykov

Möglicherweise führt dies zu einem falschen Verhalten, da der Datei-Api fs.readdir kein Versprechen zurückgibt. Es braucht nur einen Rückruf. Wenn Sie die async-await-Syntax verwenden möchten, können Sie die Funktion folgendermaßen "versprechen":

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

und nenne es stattdessen:

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

Node.js 8.0.0

Native Async/Erwartung

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
}

Verwendungszweck

Verwenden Sie immer try..catch für Aufwarteblöcke, wenn Sie die Ausnahme nicht erneut starten möchten.

// in some module, with imported function 
// in async block    
const res = await readFile('data.json')
console.log(res)
28
dimpiax

Native Async erwartet Funktionen von style fs seit Version 10 [Experimental]

Seit Node.JS 10.0.0 haben Sie Zugriff auf Dateisystemmethoden, die bereits bekanntgegeben wurden. Sie können sie mit try catch-Ausnahmebehandlung verwenden, anstatt zu prüfen, ob der Rückgabewert einen Fehler enthält. 

Die API ist experimentell , aber sie ist sehr sauber und elegant! Verwenden Sie einfach .promises member von fs object:

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();
7
bman

Folgendes hat für mich funktioniert:

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);
  }
})();

Dieser Code funktioniert in Knoten 7.6 ohne Babel, wenn Harmony-Flag aktiviert ist: node --harmony my-script.js. Und beginnend mit Knoten 7.7, Sie brauchen dieses Flag nicht einmal !

Die fsp Bibliothek, die am Anfang enthalten ist, ist nur ein versprochener Wrapper für fs (und fs-ext ).

Ich bin wirklich begeistert davon, was man heutzutage in node ohne babel machen kann! Native asyncawait macht das Schreiben von Code zum Vergnügen!

_/UPDATE 2017-06: Das Modul fs-promise wurde nicht mehr unterstützt. Verwenden Sie stattdessen fs-extra mit derselben API.

5

Empfehlen Sie die Verwendung eines npm-Pakets wie https://github.com/davetemplin/async-file im Vergleich zu benutzerdefinierten Funktionen. Zum Beispiel: 

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

Andere Antworten sind veraltet

4
sean2078

Ich habe dieses kleine Hilfemodul, das versprochene Versionen von fs Funktionen exportiert

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

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