如何通过async / await异步读取和汇总所有文件的数据

时间:2016-10-13 12:10:26

标签: node.js async-await

我知道bluebird或fs-promise甚至es6 promise都可以做到。就像下面我做的那样。

但我想用最新的es7 async / await来实现。我只是不知道如何在for循环中使用async / await(然后对它们的结果求和)。

我用Google搜索的大多数示例都是关于fetch / 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 个答案:

答案 0 :(得分:3)

首先要使用async / await我们还需要Promise。仅仅因为与承诺不同,我们不能await基于回调的函数。

所以为了让它开始,我建议使用bluebird的.promisifyAll方法,所以所有fs方法都跟着&#39; Async&#39; postfix将返回promises。

至少你会:

&#13;
&#13;
'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));
&#13;
&#13;
&#13;

此代码存在问题。尝试.readFile目录时会出错。所以我们可以像这样过滤目录:

&#13;
&#13;
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;
}
&#13;
&#13;
&#13;