// 递归遍历目录
function recursion (filepath) {
fs.readdir(filepath, (err, files) => {
doSomething(); // 这里做一些收集文件信息的操作
files.forEach(file => {
recursion(file);
});
});
}
第一步:recursion(filepath);
第二步: doOtherthing();
递归遍历目录,且都是用异步的。递归的过程中会收集一些信息。
怎么样第一步与第二步是同步执行的(ps: 第二步操作主要是处理收集到的所有的信息)
刚刚入坑,不太懂,求各位大神指导
var fileNum = 0,filesInfo = []; function recursion (filepath,cb) { fs.readdir(filepath, (err, files) => { if(files && files.length){ fileNum += files.length; doSomething(); // 这里做一些收集文件信息的操作,收集的文件信息放到filesInfo里 files.forEach(file => { recursion(file,cb); }); }else{ if(fileNum === filesInfo.length){ //代表处理所有的目录完毕 cb && typeof cb === ‘function’ && cb(); } } }); } //用法 recursion(filepath, doOtherthing); 这个比较简单,就直接callback了,当然也可以包装一层promise,再加上async await
callback行不通
我想要遍历完目录后完整的获取后所有目录信息
后才能执行 doOtherthing()
说白了就是怎么才能判断所有的目录都被遍历了
,然后执行doOtherthing()
谢谢回复@yuu2lee4
@mosikoo 我感觉逻辑没错啊,fileNum === filesInfo.length 不就是所有的目录都被遍历了
兄弟,你这个判断条件用于判断遍历是否结束
感觉完全不对啊
if(fileNum === filesInfo.length){
cb && typeof cb === ‘function’ && cb();
}
filesIfno.lenght与fileNum是一直相等的。 所以遇到空的文件夹或者文件就会触发一次callback @yuu2lee4
@mosikoo 不会一直相等啊 fileNum是目录下有子目录的时候 马上就增加的。。。而filesInfo是在你recursion的时候 收集完信息才去增加的。。是个异步的过程,所以除非你收集完所有的目录信息,否则filesInfo.length是会比fileNum小的
理是这个理,但是运行的时候却不是这样,我把你的代码简化后运行下
const fs = require('fs');
const path = require('path');
var fileNum = 0,filesInfo = [];
const filepath = path.resolve(process.cwd(), process.argv[2]);
function recursion (filepath) {
fs.readdir(filepath, (err, files) => {
if(files && files.length){
fileNum += files.length;
files.forEach(file => {
const innerFilepath = path.resolve(filepath,file);
fs.stat(innerFilepath, (err, stats) => {
// doSomething(); // 这里做一些收集文件信息的操作,收集的文件信息放到filesInfo里
filesInfo.push('fileInfo');
recursion(innerFilepath);
});
});
}else{
console.log( fileNum, filesInfo.length, filepath)
if(fileNum === filesInfo.length){ //代表处理所有的目录完毕
console.log('success')
}
}
});
}
recursion(filepath);
这段代码应该能代表你的思想吧。 要不你复制下来随便找个目录运行下看下结果 再次表示感谢@yuu2lee4
之前有一个类似的需求,也是遍历目录,然后实在没想到解法,就用readdirSync把程序写出同步的了
@sirqiao 怒了 用promise async吧,前提是你需要将readdir和stat promise化(找个promisify的包)。。。
async function recursion (filepath) {
let [files,stat] = await Promise.all([fs.readdir(filepath), fs.stat(filepath)]);
let res = [stat];
if(files && files.length){
const promises = files.map(function (file) {
const innerFilepath = path.resolve(filepath,file);
return recursion(innerFilepath);
});
const stats = await Promise.all(promises);
for(let item of stats){
res = res.concat(item);
}
}
return res;
}
最后大概就是这个样子
自用的一个 readdirp 的部分截取
'use strict';
const fs = require('fs');
const path = require('path');
const _ = require('lodash');
const ignore = require('./ignore.js');
function readDirectory(_path, ignorePattenList, callback) {
if (typeof ignorePattenList === 'function') {
callback = ignorePattenList;
ignorePattenList = [];
}
let result = {
path: _path,
name: path.basename(_path),
type: 'directory'
};
fs.readdir(_path, function (error, files) {
if (error) {
return callback(error);
}
_.remove(files, function (file) {
return ignore(file, ignorePattenList);
});
let length = files.length;
if (length <= 0) {
return callback(undefined, result);
}
result.children = [];
files.forEach(function (file) {
let filePath = path.resolve(_path, file);
fs.stat(filePath, function (error, fileStat) {
if (error) {
return callback(error);
}
if (fileStat.isDirectory()) {
readDirectory(filePath, ignorePattenList, function (error, _result) {
if (error) {
return callback(error);
}
result.children.push(_result);
length -= 1;
if (length <= 0) {
return callback(undefined, result);
}
});
} else {
result.children.push({
path: filePath,
name: file,
type: 'file'
});
length -= 1;
if (length <= 0) {
return callback(undefined, result);
}
}
});
});
});
}
module.exports = readDirectory;
let targetPath = '/Users/fei/code/';
readDirectory(targetPath, ['.*', 'node_modules'], function (error, tree) {
// 已经读取所有文件,做接下来想要做的事情
console.log(JSON.stringify(tree, undefined, 4));
});
不懂,放在forEach后面执行不就行了?建议使用async await异步解决方案,或者promise 自豪地采用 CNodeJS ionic
@DuanPengfei 6666, 实现了@yuu2lee4 说的第一种callback方法。
@yuu2lee4 膜拜大神。 最后一个问题。4.X版本的node想要兼容promise与async要引入哪些插件。
@mosikoo 这个你搜一下或者请教专业的node开发人员来回答吧。。。我主要还是做前端的。。。^_^。。。我知道promise可以用bluebird吧。。async好像就有叫async的包,然后用babel转也可以。。。官方的api可以用promisify转为promise的api
@yuu2lee4 3Q啦
readdirSync
啊。
你需要这个: sas:回调地狱终结者