Использование файловой системы в 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, все в порядке, и я получаю имена файлов.
Спасибо за ваши подсказки.
Ответы
Ответ 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
, включенная в начало, - это всего лишь многообещающая оболочка для fs
(и fs-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();
Ответ 9
если вы хотите понять шаг за шагом, вы можете посмотреть это видео https://clk.ink/filesystem-video
также вы можете использовать этот код легко
https://clk.ink/filesystem