异步for循环:如何让for循环等待函数完成?

时间:2014-08-01 17:05:29

标签: javascript node.js asynchronous

我正在试图弄清楚如何对这个/地方回调进行排序以获得我需要的东西。

我有一个检查文件是否存在的循环。我希望在完成后回调,但for循环和回调在" fs.open"之前完成。完成...典型的异步问题。

我正在使用节点v0.10.29 表达v3.14.0 ,正在使用" async "库,但是,再一次,我不能弄清楚我需要的逻辑......

这就是我所拥有的:

输入

function checkForAllFiles(callback)
{
    var requiredFiles = [];
    requiredFiles[requiredFiles.length] = "../Client/database/one.js";
    requiredFiles[requiredFiles.length] = "../Client/database/two.dat";
    requiredFiles[requiredFiles.length] = "../Client/database/three.xml";
    requiredFiles[requiredFiles.length] = "../Client/database/four.dat";
    requiredFiles[requiredFiles.length] = "../Client/database/five.dat";
    requiredFiles[requiredFiles.length] = "../Client/database/six.xml";

    var missingFiles = [];
    for(var r=0; r<requiredFiles.length; r++)
    {
        fs.open(requiredFiles[r], 'r', function(err, fd){
            if(err)
            {
                missingFiles[missingFiles.length] = err.path;
                console.log("found missing file = ", err.path);
            }
        });
        console.log("r = ", r);
    }
    console.log("sending callback: ", missingFiles);
    callback(missingFiles);
}

输出

0
1
2
3
4
5
sending callback: []
found missing file: ../Client/database/three.xml

期望输出

0
1
found missing file: ../Client/database/three.xml
2
3
4
5
sending callback: ["../Client/database/three.xml"]

2 个答案:

答案 0 :(得分:3)

我会在异步模块中使用reject方法(我看到你已经找到了)。它将做的是在其回调中返回一个数组,该数组包含匹配指定检查函数的任何元素。对于检查功能,我建议您只使用fs.exists而不是在fs.open上查看错误。

使用这些功能,您实际上可以将整个检查减少到一行。像这样:

function checkForAllFiles(callback)
{
    var requiredFiles = [];
    requiredFiles[requiredFiles.length] = "../Client/database/one.js";
    requiredFiles[requiredFiles.length] = "../Client/database/two.dat";
    requiredFiles[requiredFiles.length] = "../Client/database/three.xml";
    requiredFiles[requiredFiles.length] = "../Client/database/four.dat";
    requiredFiles[requiredFiles.length] = "../Client/database/five.dat";
    requiredFiles[requiredFiles.length] = "../Client/database/six.xml";

    async.reject(requiredFiles, fs.exists, callback);
}
将使用仅包含不存在的文件的数组调用

callback

答案 1 :(得分:1)

使用async库和eachSeries方法。例如:

async.eachSeries(array,
     function(element, next) {
          // do something with element
          next();
     }
);

它将按顺序遍历数组并处理每个元素。接下来调用下一个元素。系列确保它按照数组的顺序执行,否则无法保证通过数组的顺序。如果你在其中调用了其他异步函数,只需传递下一个函数并在完成所有需要的函数时调用它,然后处理下一个数组元素。

也许是这样的:

var missingFiles = []
async.eachSeries(requiredFiles, function(file, nextFile){
 fs.open(file, 'r', function(err, fd){
        if(err)
        {
            missingFiles[missingFiles.length] = err.path;
            console.log("found missing file = ", err.path);
        }
       nextFile();
    });
    console.log("r = ", file);
});
console.log("sending callback: ", missingFiles);
callback(missingFiles);