【问题标题】:For-loop and async callback in node.js?node.js中的for循环和异步回调?
【发布时间】:2011-11-08 06:36:01
【问题描述】:

我是 JavaScript 和 node.js 的新手。我想遍历一个目录并将所有文件统计信息(不是其他目录)添加到一个数组中。正如您在下面看到的,我的代码存在问题,因为在 for 循环完成后可能会调用回调,因此在回调方法中使用“i”变量将不起作用。但是代码应该如何看起来才能使下面的 sn-p 工作?它与闭包有关吗?

感谢您的帮助!

    fs.readdir(SYNCDIR, function(err1, files) {
        var filesOnly = [];

        if(!err1) {

            for(var i = 0; i < files.length; i++) {

                var imgFilePath = SYNCDIR + '/' + files[i];
                fs.stat(imgFilePath, function(stat){

                    if (stat.isFile()){
                        filesOnly[i] = stat; // This will not be correct since the for-loop has finished
                    }
                });

            }
        }
    });

【问题讨论】:

标签: node.js asynccallback


【解决方案1】:

关于需要使用闭包你是对的。您应该将for 循环的内容包装在一个自调用函数中,以便为每次迭代保留i 的值。

fs.readdir(SYNCDIR, function(err1, files) {
    var filesOnly = [];

    if(!err1) {

        for(var i = 0; i < files.length; i++) {

            (function(i) {
                var imgFilePath = SYNCDIR + '/' + files[i];
                fs.stat(imgFilePath, function(stat){
                    if (stat.isFile()){
                        filesOnly[i] = stat;
                    }
                });
            })(i);

        }
    }
});

【讨论】:

  • 非常感谢。帮助很大
【解决方案2】:

一种方法是重写循环的内部结构以使用闭包:

fs.readdir(SYNCDIR, function(err1, files) {
    var filesOnly = [];
    if(!err1) {
        for(var i = 0; i < files.length; i++) {
            (function(index) {
                var imgFilePath = SYNCDIR + '/' + files[index];
                fs.stat(imgFilePath, function(stat){
                    if (stat.isFile()){
                        filesOnly[index] = stat;
                    }
                });
            })(i);
        }
    }
});

一个更好看的例子,实现了同样的效果,使用 Array.prototype.forEach:

fs.readdir(SYNCDIR, function(err1, files) {
    var filesOnly = [];
    if(!err1) {
        files.forEach(function(file, i) {
            var imgFilePath = SYNCDIR + '/' + file;
            fs.stat(imgFilePath, function(stat){
                if (stat.isFile()){
                    filesOnly[i] = stat;
                }
            });
        });
    }
});

【讨论】:

  • +1 表示.forEach 方法。这要容易得多,并且避免为每次迭代创建新的绑定范围。
【解决方案3】:

或者使用新的线程模块 (https://github.com/robtweed/Q-Oper8),然后您可以在线程子进程中使用标准同步编码更简单地完成所有这些工作,因为它们一次只处理一个用户的请求。

告别异步逻辑和嵌套回调!

【讨论】:

    猜你喜欢
    • 2015-04-11
    • 2014-02-06
    • 1970-01-01
    • 1970-01-01
    • 2017-06-16
    • 2015-02-11
    • 2021-10-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多