171 votes

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

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

Mais avec ce code, je me retrouve dans le cas où names est indéfinie :

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

Lorsque je reconstruis le code dans la version callback hell tout est OK et j'obtiens les noms de fichiers. Merci pour vos conseils.

163voto

Azbykov Points 687

À partir du nœud 8.0.0, vous pouvez l'utiliser :

const fs = require('fs');
const util = require('util');

const readdir = util.promisify(fs.readdir);

async function myF() {
  let names;
  try {
    names = await readdir('path/to/dir');
  } catch (err) {
    console.log(err);
  }
  if (names === undefined) {
    console.log('undefined');
  } else {
    console.log('First Name', names[0]);
  }
}

myF();

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

7 votes

Dans le nœud v8.9.4, j'ai obtenu une SyntaxError: Unexpected token import message d'erreur. le node8 supporte-t-il import par défaut ?

9 votes

@makerj il utilise la nouvelle import la syntaxe. Elle nécessite actuellement une certaine transpilation. Il serait bon d'utiliser également const fs = require('fs') o const { promisify } = require('util')

2 votes

Question d'amateur, mais quelle est la {err, names} = function syntaxe appelée ?

152voto

Dane Points 311

Support natif des fonctions async await fs depuis Node 11

Depuis Node.JS 11.0.0 (stable), et la version 10.0.0 (expérimentale), vous avez accès à des méthodes de système de fichiers qui sont déjà promises et vous pouvez les utiliser avec try catch la gestion des exceptions plutôt que de vérifier si la valeur retournée par la callback contient une erreur.

L'API est très propre et élégante ! Il suffit d'utiliser .promises membre de fs objet :

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

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

listDir();

0 votes

Cette API est stable à partir de la version 11.x selon la norme Documentation sur les systèmes de fichiers sur le site de Node.js

5 votes

@DanStarns si vous ne le faites pas. return await votre promesse, le bloc catch n'est d'aucune utilité... Je pense que c'est parfois une bonne pratique d'attendre avant de revenir

0 votes

@538ROMEO je viens de regarder ça et vous avez raison. Merci de l'avoir signalé.

99voto

dimpiax Points 96

Node.js 8.0.0

Native async / await

Promisify

A partir de cette version, vous pouvez utiliser la fonction native de Node.js à partir de utilitaire bibliothèque.

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

Emballage de la promesse

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

Conseils

Utilisez toujours try..catch pour les blocs await, si vous ne voulez pas relancer l'exception supérieure.

0 votes

C'est étrange. J'obtiens SyntaxError : await is only valid in async function... pleurant de rage.

2 votes

@VedranMaricevic. Regardez les commentaires, await doit toujours être en async bloc :)

0 votes

@VedranMaricevic. Vous devez appeler ça const res = await readFile('data.json') console.log(res) dans une fonction asynchrone

46voto

wursttheke Points 281

Il se peut que vous produisiez un comportement erroné parce que le File-Api fs.readdir ne renvoie pas de promesse. Il prend seulement un callback. Si vous voulez utiliser la syntaxe async-await, vous pouvez "promettre" 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 l'appeler à la place :

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

0 votes

J'obtiens une réponse bizarre comme ceci... Buffer(18524) [60, 115, 99, 114, 105, 112, 116, 32, 116, 110, 116, 45, 108, 105, 98, 62, 13, 10, 32, 32, 32, 32, 47, 42, 42, 13, 10, 32, 32, 32, 32, 42, 32, 67, 111, 112, 121, 114, 105, 103, 104, 116, 32, 63, 32, 50, 48, 50, 48, 32, 68, 101, 115, 105, 103, 110, 32, 65 ...]

1 votes

Utilisez Buffer.toString méthode.

5voto

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 node 7.6 sans babel lorsque drapeau d'harmonie est activé : node --harmony my-script.js . Et à partir du nœud 7.7, vous n'avez même pas besoin de ce drapeau !

El fsp incluse au début n'est qu'une enveloppe promise pour la bibliothèque fs (et fs-ext ).

Je suis vraiment excité par ce que l'on peut faire dans node sans babel de nos jours ! Native async / await font de l'écriture du code un tel plaisir !

MISE À JOUR 2017-06 : Le module fs-promise a été déprécié. Utilisez fs-extra à la place avec la même API.

0 votes

Télécharger une bibliothèque pour cela est une pure surenchère, le gonflement des dépendances est quelque chose que la communauté devrait fortement combattre, en fait un nouveau npmjs devrait voir le jour qui n'aurait que des librairies avec 0 dépendance.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X