OurJS


OurJS-我们的JS, 我们的技术-IT文摘; 专注JS相关领域;
我们热爱编程, 我们热爱技术;我们是高大上, 有品味的码农;

欢迎您订阅我们的技术周刊


我们会向您分享我们精心收集整理的,最新的行业资讯,技术动态,外文翻译,热点文章;
我们使用第三方邮件列表向您推送,我们不保存您的任何个人资料,注重您的隐私,您可以随时退订,

欢迎分享您的观点,经验,技巧,心得

让我们一起找寻程序员的快乐,探索技术, 发现IT人生的乐趣;


本网站使用缓存技术每次加载仅需很小流量, 可在手机中流畅浏览;
如果您发现任何BUG,请即时告知我们: ourjs(at)ourjs.com

Node.JS中如何判断递归嵌套的所有回调函数已经执行完毕,以读取目录下所有文件为例:计数比Promise方式快将近一倍


分享到
分类 JS学习   关键字 Node.JS   发布 kris  1493950875801
注意 转载须保留原文链接,译文链接,作者译者等信息。  

当一个Node.JS函数中有大量的异步操作时,如何判断所有回调均已完成就成为一个问题。以递归读取一个目录下的所有文件为例,可以有两种方法来判断异步函数是否全部结束:

Promise 方法

Promise有一个 all 方法:

Promise.all(iterable) 方法指当所有在可迭代参数中的 promises 已完成,或者第一个传递的 promise(指 reject)失败时,返回 promise。


实现代码如下所示,来自 William17

var fs        = require('fs');
var readdir   = promisify(fs.readdir);
var stat      = promisify(fs.stat);
var readFile  = promisify(fs.readFile);

// 简单实现一个promisify
function promisify(fn) {
  return function() {
    var args = arguments;
    return new Promise(function(resolve, reject) {
      [].push.call(args, function(err, result) {
        if(err) {
          console.log(err)
          reject(err);
        }else {
          resolve(result);
        }
      });
      fn.apply(null, args);
    });
  }
}

function readDirRecur(file, callback) {
  return readdir(file).then((files) => {
    files = files.map((item) => {
      var fullPath = file + '/' + item;

      return stat(fullPath).then((stats) => {
          if (stats.isDirectory()) {
              return readDirRecur(fullPath, callback);
          } else {
            /*not use ignore files*/
            if(item[0] == '.'){
              //console.log(item + ' is a hide file.');
            } else {
              callback && callback(fullPath)
            }
          }
        })
    });
    return Promise.all(files);
  });
}

var fileList = []

var timeStart = new Date()

readDirRecur('D:/github/oncedoc', function(filePath) {
  fileList.push(filePath)
}).then(function() {
  console.log('done', new Date() - timeStart);
  console.log(fileList);
}).catch(function(err) {
  console.log(err);
});

计数方法:

计数是比较常用的一种方法,其原理类似于c/c++中的引用计数,实现起来比较容易:

var fs        = require('fs');

function readDirRecur(folder, callback) {
  fs.readdir(folder, function(err, files) {
    var count = 0
    var checkEnd = function() {
      ++count == files.length && callback()
    }

    files.forEach(function(file) {
      var fullPath = folder + '/' + file;

      fs.stat(fullPath, function(err, stats) {
        if (stats.isDirectory()) {
            return readDirRecur(fullPath, checkEnd);
        } else {
          /*not use ignore files*/
          if(file[0] == '.') {

          } else {
            fileList.push(fullPath)            
          }
          checkEnd()
        }
      })
    })

    //为空时直接回调
    files.length === 0 && callback()
  })
}

var fileList  = []
var timeStart = new Date()

readDirRecur('D:/github/oncedoc', function(filePath) {
  console.log('done', new Date() - timeStart);
  console.log(fileList);
})

测试结果比较:

Promise法,耗时 6.2 秒 左右

$ node test.promise.js
done 6214
[ ...
  ... 55621 more items ]

计数法,耗时 3.5秒左右

$ node test.count.js
done 3590
[ ...
  ... 55621 more items ]

由此可见,计数法比Promise快将近1倍左右。

社区评论 ( Beta版 )
OnceDoc 您自己的企业内容管理系统——文档、流程、知识库、报表、网盘All In One

访问404页面,寻找丢失儿童
 热门文章 - 分享最多
  1. JavaScript使用ES6的Class面向对象继承时 this is not defined 解决方法
  2. Java已快过时?斯坦福大学将JavaScript作为计算机科学入门课
  3. Docker改名Moby:急于商业化陷入品牌更名乱象
  4. JavaScript条形码生成和扫码识别(Barcode scan)开源库
  5. TCP/UDP协议比较:在Node.JS中UDP服务器和客户端通信示例
  6. OnceVI前后端分离的数据可视化报表工具简介
  7. Node.JS通过原型和类继承EventEmitter,实现收发事件的几种方法
  8. 2016 年崛起的 JS 项目
  9. 如何基于SVG矢量图制作一个可填写信息的可视化表单-OnceVI
  10. 周鸿祎:一些程序员没有商业意识,却又很自负,一看就知道不会创业
  11. AirJD-简单好用的免费建站工具

 相关阅读 - JS学习
  1. Node.js网页抓取:一个最简单的http请求客户端示例(request client)
  2. JavaScrip字符串模板表达式中的反引号怎么打?
  3. Node.JS用Socket实现FTP Server服务器和Client客户端
  4. Node.JS更改Windows注册表regedit的几种方法
  5. Debian下设置Linux Shell脚本开机自动启动Node.JS进程
  6. Node.JS通过原型和类继承EventEmitter,实现收发事件的几种方法
  7. 可视化Web报表OnceVI中用户输入表单验证与提交
  8. Web报表OnceVI如何制作条形码与打印二维码(Barcode/Qrcode)
  9. 如何基于SVG矢量图制作一个可填写信息的可视化表单-OnceVI
  10. OnceVI报表制作入门—如何将用户的json数据可视化成名片展示

 关键字 - Node.JS
  1. 理解Node.js的事件循环(Event Loop)和线程池
  2. Node.JS中如何快速扫描端口并发现局域网内的Web服务器地址(80)
  3. Express入门教程:一个简单的博客
  4. Node.JS循环递归复制文件夹目录及其子文件夹下的所有文件
  5. Oracle发布官方版Node.JS数据库驱动
  6. 为什么你应该抛弃Express的视图渲染引擎
  7. 在OnceIO(Node.JS)中用Redis储存Session
  8. Node.js中的通用基础设计模式
  9. 沃尔玛为什么要采用Node.js
  10. node.js使用unzip解压zip包指定文件,提取 word/excel (docx/pptx/xlsx) 文本内容

 欢迎订阅 - 技术周刊

我们热爱编程, 我们热爱技术; 我们是高端, 大气, 上档次, 有品味, 时刻需要和国际接轨的码农; 欢迎您订阅我们的技术周刊; 您只需要在右上角输入您的邮箱即可; 我们注重您的隐私,您可以随时退订.
加入我们吧! 让我们一起找寻码农的快乐,探索技术, 发现IT人生的乐趣;


 关注我们

我们的微信公众号: ourjs-com
打开微信扫一扫即可关注我们:
IT文摘-程序员(码农)技术周刊

ourjs官方微信号