Node.js中循环异步函数内的未定义变量

时间:2014-10-31 18:20:08

标签: javascript node.js loops asynchronous scope

我正在构建一个在服务器启动或文件夹更改时自动扫描文件夹的功能。该脚本将为已安装的小部件组装一个小部件文件夹,然后连接并构建一个新的部分文件以包含在前端应用程序中。

脚本如下:

concat.readMethodContents = function(concat) {

    var widget;
    for (widget in concat.widgets) {

        var method;
        for (method in concat.widgets[widget]) {

            if (concat.widgets[widget][method].ready) {
                concat.widgets[widget][method].ready = false;

                fs.readFile('./lib/widgets/' + widget + '/methods/' +  concat.widgets[widget][method].handle, 'utf8', function(err, data) {
                    if (err) {
                        console.log(err);
                    } else {

                        concat.widgets[widget][method].contents = data;

                        concat.writeJsPartialFile(concat);
                    }
                });
            }
        }
    }
}

在调用此方法之前, concat 对象如下所示:

{
    "widgets": {
        "hello_world": [{
            "handle": "method1.js",
            "ready": true
        }, {
            "handle": "method2.js",
            "ready": true
        }, {
            "handle": "method3.js",
            "ready": true
        }]
    }
}

脚本的问题是,当调用方法时,它被定义为 done ,因为循环已完成且异步函数正在运行回调。

如何通过操作的那一部分封装或保存变量?

1 个答案:

答案 0 :(得分:1)

我刚才在这里回答了同样的问题:Accessing a MongoDB value from a query within a query

使用自执行函数来封装闭包,以确保由于循环而值不会在您下面发生变化。尝试类似:

concat.readMethodContents = function(concat) {
    var widget;
    for (widget in concat.widgets) {
        var method;
        for (method in concat.widgets[widget]) {
            (function(widgetMethod) {
                if (widgetMethod.ready) {
                    widgetMethod.ready = false;
                    fs.readFile('./lib/widgets/' + widget + '/methods/' +  widgetMethod.handle, 'utf8', function(err, data) {
                        if (err) {
                            console.log(err);
                        } else {
                            widgetMethod.contents = data;
                            concat.writeJsPartialFile(concat);
                        }
                    });
                }
            })(concat.widgets[widget][method]);
        }
    }
}