node批量读取文件时异步变同步的方法分享

来源:互联网 发布:shop 源码下载 编辑:程序博客网 时间:2024/06/18 11:51

需求,读取一个文件夹下面的文件,并且获取其中的文件夹名字:

编码:

var fs=require('fs');

var dir=[];//定义一个数组,存放文件夹的名字

fs.readdir('./',function(err,files){ //读取根目录下的所有文件,files为所有文件名字的集合

for(var i=0;i<files.length;i++){//遍历文件名

 var theFilename=files[i];//存放遍历时某个文件的名字

 fs.stat('./'+theFilename,function(err,stats){//读取具体的某个文件内容

  if(stats.isDirectory()){//判断是不是文件夹

    dir.push(theFilename);

  }

 });

console.log(dir);

}

});


//上面这个代码有个问题,无论如何检测结果都是files集合最后一个文件的集合,为什么呢?因为异步。

当node遇到这个代码时: fs.stat('./'+theFilename,function(err,stats){//读取具体的某个文件内容  

它直接又去执行第二次循环了,并没有等读取完成再循环,所以等读取完成执行回调函数时, var theFilename=files[i];//存放遍历时某个文件的名字已经是读取到最后一个文件了

怎么解决这个问题呢?

有两个思路:

1.把异步变成同步

2.用闭包,隔离每次循环得到的files[i];


先说第一种:

既然要变成同步读取,那就不能用循环遍历的方法去读取每个文件了,因为stat方法是异步的,当然也有同步的读取方法,但是我们这里不考虑这个。

不通过循环遍历创建多个stat方法读取文件集合,那还有什么方法呢?自然而然就想到递归,递归和循环是读取集合的常用方法。

我们可以先指定读取第一个文件,然后再回调函数里面再指定读取下一个文件,一直读取到最后一个。

思路有了,那开始编码:

var fs=require('fs');

fs.readdir('./',function(err,files){

 (function getDir(i){

    if(i==files.length){return;}

     fs.stat('./'+files[i],function(err,stats){

        if(stats.isDirectory()){

         dir.push(files[i]);

         }

        getDir(i++);//继续读取下一个文件,执行到这里说明当前文件已经读取完毕

     })

  })(0)

});


利用在回调里面递归我们同样实现了同步读取文件的效果,但是单个文件来看,读取依然是异步,只是我们只有一个文件读取任务的时候,同步异步也就没差别了。利用递归就能实现多个文件的同步读取



接下来说一下用闭包实现:

分析,之前代码之所以有问题就是因为i的值的问题,因为在读取文件结束后i已经是最后一个值了,那如果我们用闭包隔离每次遍历的i的值呢?这样就不会有问题了:

代码:

fs.readdir('./',function(err,files){    for(var i=0;i<files.length;i++){        (function(i){            var theFilename=files[i];            fs.stat('./'+theFilename,function(err,stats){                if(stats.isDirectory()){                    dir.push(theFilename);                    console.log(dir);                }            })        })(i)    }})

//每次i的值都放在一个闭包里面,当运行结束时实际上是有多个i在不同的作用域里面,各自调用各自的i,这样同样达到要求,喜欢那种方法主要看爱好,但是我更加推荐第二种,因为它更加符合node的规范,多个异步读取时间同时存在而不是控制只有一个异步同时存在来达到同步的效果。


0 0
原创粉丝点击