nodejs 异步递归遍历文件

nodejs 同步递归遍历文件是非常简单的,异步递归遍历是就稍许复杂了一些

异步递归遍历可以采用类似迭代器的方式进行;首先定义一个方法,回调函数拥有三个参数 分别是 err, file, next

function travelSync(dir, callback){
}
/**
 * 执行方法
 */
 travelSync('E:/runs', function (e, file, next) {
     //处理文件
    console.log(file);
    //获取下一个文件
    next();
});

当遍历完一个文件夹后,需要进行遍历下一个(next)文件,并且当前目录遍历完成后,若存在父级文件夹则遍历父级文件夹的未遍历的。那怎么判断已经遍历完成 和 遍历下一个文件?需要定位当前遍历位置,且当前目录遍历完后接着遍历下一个文件夹。可以在travelSync内部定义一个 参数 i 用于记录当前位置,并在 travelSync 新增一个参数 finish 用于定位当前目录遍历完成进行遍历下一个父级目录文件


function travelSync(dir, callback, finish){
    fs.readdir(dir, function (e, files) {
            // i 用于定位当前遍历位置
            function next(i) {
                // 当i >= files 表示已经遍历完成,进行遍历下一个文件夹
                if(i < files.length){
                }else{
                    finish && finish();
                }
            };
    });
}

当前遍历对象是目录时进行递归调用,当前的位置通过 封装在一个闭包里面 传递到 travelSync 的 finish 参数中,当子目录遍历完成后,通过执行 finish 进行遍历下一个文件(finish中记录了遍历位置)。
遍历对象为文件时将 文件对象(file) 和 当前遍历位置传递(next) 到 回调方法 callback 中,并在回调方法 callback 处理完成后,执行 next 遍历下一个文件。
当 i >= files 时 表示当前文件夹遍历完成,进行遍历父级目录执行 finish 方法,这里需要明白的是, finish 是递归调用时 传进来的方法,实际finish 方法内部调用了 next(i) 方。因为首次调用时 finish 方法 没有传入 所以 应判断 finish 是否存在。


function travelSync(dir, callback, finish){
    fs.readdir(dir, function (e, files) {
          // i 用于定位当前遍历位置
         (function next(i) {
              // 当i >= files 表示已经遍历完成,进行遍历下一个文件夹
             if(i < files.length){
                 var pathname = path.join(dir, files[i]);
                 if(fs.stat(pathname, function (e, stats) {
                     if(stats.isDirectory()){
                         travelSync(pathname, callback, function () {
                             next(i + 1);
                         });
                     }else{
                         callback(e, pathname, function () {
                             next(i + 1);
                         });
                     }
                 }));
             }else{
                 /**
                  * 当 i >= files.length 时,即表示当前目录已经遍历完了, 需遍历下一个文件夹
                  * 这里执行的时递归调用 传入的 方法 , 方法里调用了 next(i) 记录了当前遍历位置
                  */
                 finish && finish();
             }

         })(0);
    });
}

 travelSync('E:/runs', function (e, file, next) {
     //处理文件
    console.log(file);
    //获取下一个文件
    next();
});

如此便可以进行正常的遍历了文件了,下面为完成的代码

var fs = require('fs');
var path = require('path');

function travelSync(dir, callback, finish){
    fs.readdir(dir, function (e, files) {
         if (e === null) {
            // i 用于定位当前遍历位置
            (function next(i) {
                 // 当i >= files 表示已经遍历完成,进行遍历下一个文件夹
                if(i < files.length){
                    var pathname = path.join(dir, files[i]);
                    if(fs.stat(pathname, function (e, stats) {
                        if(stats.isDirectory()){
                            travelSync(pathname, callback, function () {
                                next(i + 1);
                            });
                        }else{
                            callback(e, pathname, function () {
                                next(i + 1);
                            });
                        }
                    }));
                }else{
                    /**
                     * 当 i >= files.length 时,即表示当前目录已经遍历完了, 需遍历下一个文件夹
                     * 这里执行的时递归调用 传入的 方法 , 方法里调用了 next(i) 记录了当前遍历位置
                     */
                    finish && finish();
                }

            })(0);
        }else{
            callback(e);
        }
    });
}
travelSync('E:/runs', function (e, file, next) {
    if(e !== null){
        console.log(e); 
    }
    console.log(file);
    //获取下一个文件 next 里面调用了 next(i) 记录了当前遍历位置
    next();
});

猜你喜欢

转载自blog.csdn.net/wbxx727124/article/details/80279979