CNode

如何知道异步foreach已经执行完毕?

Cciiii发布于12 年前最后回复9 年前29 回复18074 浏览0 收藏

如下有个遍历文件夹的函数,如何才能得知它已经遍历结束了? 谢谢!

function walk(path, floor, handleFile) {
//    handleFile(path, floor);
    floor++;
    fs.readdir(path, function(err, files) {
        if (err) {
            console.log('read dir error');
        } else {
            files.forEach(function(item) {

                var tmpPath =path + '/' + item;
                fs.stat(tmpPath, function(err1, stats,people,factor) {
                    if (err1) {
                        console.log('stat error');
                    } else {
                        if (stats.isDirectory()) {
                            walk(tmpPath, floor, handleFile);
                        } else {
                            handleFile(tmpPath,item, floor);
                        }
                    }
                })
            });
        }
    });
}
查看回复

回复 (28)

S
sunfuze#1·12 年前

async这个库把

A
alsotang#2·12 年前

https://github.com/alsotang/eventr 来进行消息同步

C
ciiii#3·12 年前

如果用wind,该怎么写呢?

C
ciiii#4·12 年前

@thesadboy 临时抱佛脚看了半天wind,最后才觉得全部用同步调用好像是最直接的。

C
ciiii#5·12 年前
C
ciiii#7·12 年前

水平不够,wind的文档真难看懂。。。突袭到了半夜模仿着写了,心里没底,请指点下,谢谢: 1 这么样用异步函数+异步流程控制库,和直接用同步函数+个nexttick有什么区别? 2 有forEach、递归的方法,如何既利用异步的高效性,又能得到全部执行完毕的点?

var fs = require('fs'); var Wind = require('Wind'); var Binding = Wind.Async.Binding;

var myPath = 'e:/nodejs/home/public'; fs.readdirAsync = Binding.fromStandard(fs.readdir); fs.statAsync = Binding.fromStandard(fs.stat);

var walk = eval(Wind.compile("async",function (path, floor, handleFile) { floor++;

var myReadDirResult = $await(fs.readdirAsync(path));

//不知道为什么,forEach不行
for(var i = 0 ; i < myReadDirResult.length ; i++ ){
    var item = myReadDirResult[i];
    var tmpPath = path + '/' + item;
    console.log('tmpPath:' + tmpPath);

    var myStatResult = $await(fs.statAsync(tmpPath));
    if (myStatResult.isDirectory()){
        $await(walk(tmpPath, floor, handleFile).start());
    }
    else{
        handleFile(tmpPath);
    }
}
console.log(path + '文件夹结束');

}));

var main = eval(Wind.compile("async",function () { $await(walk(myPath, 0, function(filePath){ }).start()); console.log('结束'); }));

main().start();

console.log('这是最后一行');

N
ngot#8·12 年前

异步坑死人

Y
yunheli#9·12 年前

弄个变量在回调函数里累加,变量的大小等于文件的个数不就知道遍历完成了么

N
ngot#10·12 年前
引用 ciiii水平不够,wind的文档真难看懂。。。突袭到了半夜模仿着写了,心里没底,请指点下,谢谢: 1 这么样用异步函数+异步流程控制库,和直接用同步函数+个nexttick有什么区别? 2 有forE...

@ciiii 顺手用fibjs改写一下

var fs = require("fs");
(function walk(path, floor, handleFile) {
	floor++;
	var files = fs.readdir(path);
	files.forEach(function(item) {
		if (item.name !== '.' && item.name !== '..') {
			var tmpPath = path + "/" + item.name;
			if (fs.stat(tmpPath).isDirectory())
				walk(tmpPath, floor, handleFile);
			else
				handleFile.call(null, tmpPath, item, floor);
		}
	});
})(".", 0, function(tmpPath, item, floor) {
	console.log(tmpPath, item.name, floor);
});

C
ciiii#16·12 年前
引用 ciiii水平不够,wind的文档真难看懂。。。突袭到了半夜模仿着写了,心里没底,请指点下,谢谢: 1 这么样用异步函数+异步流程控制库,和直接用同步函数+个nexttick有什么区别? 2 有forE...

@ngot 以上面你的代码为例,可以这样理解不: var files = fs.readdir(path);中的files其实仍然是异步的(不管他怎么实现的),是在将来某个不确定的时间点才能返回结果的。连带着下一句:files.forEach(..., 也是将来某个不确定的时候才会真正执行。 但如果是个和files无关的语句,是会继续执行,是有可能在readdir之前执行的。 也就是说和node一样,代码字面的顺序并非执行的顺序。既然如此,哪来的“js层面同步”呢?

T
tulayang#18·12 年前
function walk (path, handleFile, callback) {
    var len = 1,       // 文件|目录数,起始一个
        floor = 0;     // 第x个目录?

    function done () {
    // 完成任务, 运行回调函数
        if (--len === 0) {
            callback();
        }
    }

    function composeErr (err) {
    // 错误处理
        console.log('stat error');
        done();  // 以错误内容完成
    }

    function composeDir (path) {
    // 目录处理
        floor++;
        fs.readdir(path, function (err, files) {
            if (err) {
                console.log('read dir error');
                done();  // 目录完成 
                return;
            }
            len += files.length;  // 子文件|子目录计数
            files.forEach(function (filename) {
                compose(path + '/' + filename);  // 子内容新的操作
            });
            done();  // 目录完成
        });
    }
 
    function composeFile (path) {
    // 文件处理
        handleFile(path, floor);
        done();  // 文件完成
    }

    function compose (path) {
        fs.stat(path, function (err, stats) {
            if (err) {
                composeErr(err);
                return;
            }

            if (stats.isDirectory()) {
                composeDir(path);
                return;
            }

            composeFile(path);
        });
    }

    compose(path);
}
C
ciiii#19·12 年前
引用 tulayang

@tulayang 3q

T
tulayang#20·12 年前
引用 tulayang

@ciiii

需要刷新一下,有些修改,但愿不存在大的bug

N
ngot#22·12 年前
引用 tulayang

@tulayang 逻辑写的很棒。不过,受限于,node.js,这么多回调,看的真不舒服。看到不优雅的代码,心里就毛毛的。

M
Mainintowhile#23·11 年前

async.map([],function(item,call) { //do...全局变量值 call(null, null) },function(err,result){ //do。。。获取变量值 })

M
magicdawn#24·11 年前

2015-11-05 16:20:38 现在别用async了

untitled1.png

#!/usr/bin/env node

'use strict';

const Promise = require('bluebird');
const fs = Promise.promisifyAll(require('fs'));
const co = require('co');

// example
const handleFile = f => f;

const walkAsync = co.wrap(function* (path) {
 var files = yield fs.readdirAsync(path);
 var ret = [];

 for(let f of files) {
   let p = path + '/' + f;
   var s = yield fs.statAsync(p);

   if (s.isDirectory()) {
     var r = yield walkAsync(p);
     ret = ret.concat(r);
   } else {
     ret.push(p)
     handleFile(p);
   }
 }

 return ret;
});

co(function *(){
 var files = yield walkAsync(__dirname);
 console.log(files);
}).catch(e => console.error(e.stack || e));
M
magicdawn#25·11 年前

不小心用了var...

J
JarvisQJ#26·9 年前

我想说,foreach不是同步的吗

D
dbit-xia#27·9 年前
引用 JarvisQJ我想说,foreach不是同步的吗

@qujinxiong 可是遍历文件夹的函数是异步呀

J
JarvisQJ#28·9 年前
引用 dbit-xia@qujinxiong 可是遍历文件夹的函数是异步呀

@dbit-xia 这是两个问题,foreach(){}之后,遍历肯定是结束了。至于里面的异步回调,...,这里应该用递归或者await来解决。

参与回复
登录后即可参与回复。登录