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

标签 node.js async-await

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

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

我用谷歌搜索的大多数例子都是关于 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);
    });
});

最佳答案

首先,要使用 async/await,我们无论如何都需要 Promise。只是因为与 Promise 不同,我们无法 await 基于回调的函数。

因此,为了开始它,我建议使用 bluebird 的 .promisifyAll 方法,这样所有带有“Async”后缀的 fs 方法都会返回 Promise。

至少您将拥有:

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

关于node.js - 如何通过 async/await 异步读取和汇总所有文件的数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40020643/

相关文章:

javascript - 在 Node.js 中设置模型的正确方法

node.js - 即使我没有使用 GROUP BY,SQL Server 的 Sequelize 也会返回错误聚合函数或 GROUP BY 子句

node.js - 在 NodeJS/Express/React 堆栈中记录错误

javascript - 为 ES 模块做 require.resolve

javascript - 为nodejs中的一系列 promise 添加延迟或 sleep

node.js - 限制对 NodeJS 中 API 的并发请求以及 Async/Await

javascript - 异步node.js :nested array with callback

c# - 异步无效方法如何报告 ASP.NET Core 应用程序中的进度

c# - 异步 FTP 上传

javascript - 在异步函数中将新对象推送到 Mongoose 中的嵌套数组