嵌套异步函数,最佳实践

时间:2015-10-07 19:27:17

标签: javascript asynchronous

我试图了解如何使用异步函数。

作为一个人,我必须转变以下功能:

var fs = require('fs');

function calculateByteSize(){
    var totalBytes = 0,
    i,
    filenames,
    stats;

    filenames = fs.readdirSync(".");
    for (i = 0; i < filenames.length; i++){
        stats = fs.statSync("./" + filenames[i]);
        totalBytes += stats.size;
    }
    console.log(totalBytes);
}
calculateByteSize();

进入异步版本。

到目前为止,我得到了:

var fs = require('fs');

function calculateByteSize(){
    var totalBytes = 0,
    i,
    stats;
    fs.readdir(".", function(err, data){
        for (i = 0; i < data.length; i++){
            fs.stat("./" + data[i],function(err, stats){
                 totalBytes += stats.size;
            }); 
        }
    });
    console.log(totalBytes);
}

calculateByteSize();

哪个有效 - 如果我在for循环期间打印'totalBytes'的值,我会得到正确的值。

但是,console.log语句打印值'0',因为它似乎在循环之前执行。

如果我在原始函数中使用statSync,那么一切正常。

我的问题是:给定函数的同步和异步版本之间的选择,最好在嵌套到异步函数时使用?

有没有办法确保在生成正确的值后执行print语句,而不使用promise? (如:Issue with nested asynchronous function not returning data in time

1 个答案:

答案 0 :(得分:1)

在节点中使用异步版本的IO绑定操作是理想的,因为环境是单线程的并且在事件循环上运行。通过这样做,您不会阻止事件循环并等待IO(在这种情况下是文件系统)。在进行此文件系统调用时,事件循环可以继续并执行其他有用的工作(例如 - 在HTTP服务器的情况下接受其他HTTP请求)。

以下是只有在所有这些字节都已添加并且没有承诺后才能记录总字节数:

function calculateByteSize(){
  var totalBytes = 0,
      statsCallsCompleted = 0,
      i,
      stats;

  fs.readdir(".", function (err, data) {
    for (i = 0; i < data.length; i++){
      fs.stat("./" + data[i], function (err, stats) {
        statsCallsCompleted += 1;
        totalBytes += stats.size;
        if (statsCallsCompleted === data.length) {
          console.log('Total Bytes:', totalBytes);
        }
      }); 
    }
  });
}