Подтвердить что ты не робот

Использование файловой системы в node.js с помощью async/wait

Я хотел бы использовать async/await с некоторыми операциями файловой системы. Обычно async/await работает нормально, потому что я использую babel-plugin-syntax-async-functions.

Но с этим кодом я запускаю случай if, где names - undefined:

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

Когда я перестраиваю код в адскую версию callback, все в порядке, и я получаю имена файлов. Спасибо за ваши подсказки.

4b9b3361

Ответ 1

Начиная с узла 8.0.0, вы можете использовать это:

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

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

Ответ 2

Node.js 8.0.0

Родной асинхронный/ожидание

Promisify

С этой версии вы можете использовать встроенную функцию Node.js из библиотеки утилит.

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


Упаковка обещаний

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

Совет

Всегда используйте try..catch для блоков ожидания, если вы не хотите перебрасывать исключение выше.

Ответ 3

Вы можете произвести неправильное поведение, потому что File-Api fs.readdir не возвращает обещание. Он требует только обратного вызова. Если вы хотите использовать синтаксис асинхронного ожидания, вы можете "обещать" эту функцию следующим образом:

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

и назовите его:

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

Ответ 4

Собственные асинхронные функции в стиле фс с версии 11

Начиная с Node.JS 11.0.0 (стабильный) и версии 10.0.0 (экспериментальный), у вас есть доступ к методам файловой системы, которые уже обещаны, и вы можете использовать их с обработкой исключений try catch, вместо того, чтобы проверять обратный вызов возвращаемое значение содержит ошибку.

API очень чистый и элегантный! Просто используйте .promises член объекта fs:

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

Ответ 5

Вот что сработало для меня:

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

Этот код работает в node 7.6 без babel, когда флаг гармонии включен: node --harmony my-script.js. И начиная с node 7.7, вам не нужен этот флаг!

Библиотека fsp, включенная в начало, - это всего лишь многообещающая оболочка для fsfs-ext).

Im действительно вышел из того, что вы можете сделать в node без babel в эти дни! Нативный async/await делает код для написания такого удовольствия!

UPDATE 2017-06: Модуль fs-prom был устарел. Используйте fs-extra вместо того же API.

Ответ 6

Рекомендуется использовать пакет npm, например, https://github.com/davetemplin/async-file, по сравнению с пользовательскими функциями. Например:

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

Другие ответы устарели

Ответ 7

У меня есть этот маленький модуль, который экспортирует Помогая promisified версии fs функций

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

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

Ответ 8

Вы можете использовать fs.Promises

const { promises: fs } = require("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();