web-dev-qa-db-fra.com

Utilisation du système de fichiers dans node.js avec async/wait

Je voudrais utiliser async/wait avec certaines opérations du système de fichiers. Normalement, async/wait fonctionne bien car j'utilise babel-plugin-syntax-async-functions.

Mais avec ce code, je rencontre le cas où names est indéfini:

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

Quand je reconstruis le code dans la version de rappel de l'enfer, tout est OK et je reçois les noms de fichiers ..__ Merci pour vos astuces.

45
Quellenangeber

À partir du noeud 8.0.0, vous pouvez utiliser ceci:

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

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

68
Azbykov

Vous risquez de générer un comportement incorrect car le fs.readdir File-Api ne renvoie aucune promesse. Cela prend seulement un rappel. Si vous voulez utiliser la syntaxe async-wait, vous pouvez "promisify" la fonction comme ceci:

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

et appelez-le à la place:

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

Node.js 8.0.0

Async natif/wait

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
}

Usage

Utilisez toujours try..catch pour les blocs d’attente si vous ne souhaitez pas rediffuser l’exception supérieure.

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

Async native attend les fonctions de style fs depuis la version 10 [Expérimental]

Depuis Node.JS 10.0.0, vous avez accès aux méthodes de système de fichiers déjà promis et vous pouvez les utiliser avec la gestion des exceptions try catch plutôt que de vérifier si la valeur de retour contient une erreur. 

L'API est expérimentale , mais elle est très propre et élégante! Utilisez simplement .promises membre de l'objet fs:

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

Voici ce qui a fonctionné pour moi:

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

Ce code fonctionne dans le nœud 7.6 sans babel lorsque le drapeau d'harmonie est activé: node --harmony my-script.js. Et à partir du noeud 7.7, vous n’avez même pas besoin de cet indicateur !

La bibliothèque fsp incluse au début est simplement un wrapper promisifié pour fs (et fs-ext ).

Je suis vraiment ravi de ce que vous pouvez faire dans node sans babel ces jours-ci! Native asyncawait: écrire du code est un vrai plaisir!

_/MISE À JOUR 2017-06: Le module fs-promise est obsolète. Utilisez fs-extra à la place avec la même API.

5
Alexander Kachkaev

Recommandez l’utilisation d’un paquet npm tel que https://github.com/davetemplin/async-file par rapport aux fonctions personnalisées. Par exemple: 

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

Les autres réponses sont obsolètes

4
sean2078

J'ai ce petit module d'aide qui exporte promisified versions de fs fonctions

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