#node.js #async-await
#node.js #async-await
Вопрос:
Я знаю, что bluebird или fs-promise или даже es6 promise могут это сделать. Как показано ниже, я сделал.
Но я хочу использовать последнюю версию es7 async / await для достижения. Я просто не понимаю, как использовать async / await в цикле for (а затем суммировать их результаты).
Большинство примеров, которые я искал в Google, касаются выборки / ajax.get. Но я хочу читать файлы и суммировать данные вместе.
Может у кого-нибудь есть подсказка? Спасибо.
var fs = require("fs");
var Promise = require("promise");
function readDir(){
var p = new Promise( function(resolve, reject) {
fs.readdir( ".", function( err, files) {
resolve(files);
})
} );
return p;
}
function readFile(file){
var p = new Promise( function(resolve, reject) {
fs.readFile( file, function( err, data) {
console.log("Successfully read a file.", file);
resolve(data);
})
} );
return p;
}
readDir().then(function(files){
var promises = [];
for ( var i = 0; i < files.length; i ) {
promises.push( readFile(files[i]) );
}
Promise.all( promises ).then( function(results) {
var totalBytes = 0;
for ( i = 0; i < results.length; i ) {
totalBytes = results[i].length;
}
console.log("Done reading files. totalBytes = " totalBytes);
});
});
Ответ №1:
Прежде всего, чтобы использовать async / await, нам все равно понадобятся обещания. Просто потому, что в отличие от promises мы не можем await
вызывать функции на основе обратного вызова.
Итак, чтобы начать, я предлагаю использовать .promisifyAll
метод bluebird, чтобы все fs
методы, за которыми следует постфикс ‘Async’, возвращали обещания.
Как минимум, у вас будет:
'use strict';
const Promise = require('bluebird');
const fs = Promise.promisifyAll(require('fs'));
async function readFile(file) {
let data = await fs.readFileAsync(file);
console.log('Successfully read a file.', file);
return data;
}
async function getTotalBytes() {
let files = await fs.readdirAsync('.');
//Making a promise for each file to read it.
let promises = files.map(f => readFile(f));
//Reading all in parallel
let results = await Promise.all(promises);
//Using native .reduce to sum the bytes
let totalBytes = results.reduce((memo, r) => {
return memo r.length;
}, 0);
console.log('Done reading files. totalBytes = ' totalBytes);
return totalBytes;
}
//Running out function
getTotalBytes()
.then(bytes => console.log(bytes))
.catch(err => console.error(err));
Существует проблема с этим кодом. При попытке доступа к каталогу будет выдана ошибка .readFile
. Таким образом, мы могли бы отфильтровать каталоги следующим образом:
async function getTotalBytes() {
let files = await fs.readdirAsync('.');
let promises = [];
for (let file of files) {
let stat = await fs.statAsync(file);
if (!stat.isDirectory()) {
promises.push(readFile(file));
}
}
let results = await Promise.all(promises);
let totalBytes = results.reduce((memo, r) => {
return memo r.length;
}, 0);
console.log('Done reading files. totalBytes = ' totalBytes);
return totalBytes;
}
Комментарии:
1. вы можете использовать util.promisify вместо добавления пакета. Подробнее здесь zeit.co/blog/node-8