同步forEach循环(等待它结束)

app*_*tix 5 javascript foreach synchronous node.js

我在Node.js中有一个函数,它接受一个数组并循环遍历它,对每个元素进行一些耗时的计算.

这是该函数的超简化版本:

var analyze_data = function (data) {
    data.forEach(function (elm) {
        if (elm.myProp == true) {
            return true;
        }
    });
    return false;
}
Run Code Online (Sandbox Code Playgroud)

本质上,如果任何元素的属性myProp等于true ,我希望函数返回true.如果所有元素都不满足此条件,则该函数应返回false.

但是,代码永远不会等待forEach循环完成.换句话说,如果数组中的第100个元素满足条件,则该函数应返回true.相反,它会return false;forEach循环有时间完成之前跳过并返回false .

这个问题有方法解决吗?

编辑

所以我意识到我过度简化了我的问题 - 我实际上使用的是Node.js包es6-promise,我的代码看起来更像是这样:

var analyze_data = function (data) {
    return new Promise(function (resolve, reject) {
        data.forEach(function (elm) {
            if (elm.myProp == true) {
                resolve(elm);
            }
        });
        resolve(false);
    });
}
Run Code Online (Sandbox Code Playgroud)

所以实际上,我没有在forEach函数中返回值而不是外部函数的问题.另外,请注意函数如何解析为元素本身而不是true,否则为false.我实际上想要返回一些相关数据,如果其中一个元素通过条件,否则返回false表示它们都失败了.

现在有什么想法?:p另外,感谢所有原始答案!

man*_*nji 6

这不是同步/异步执行的问题.你正在做的是在for each回调中返回true(对你的analyze_data函数是不可见的),然后在forEach完成后返回false.

你需要使用Array.prototype.some:

var analyze_data = function (data) {
    return data.some(function (elm) {
        return elm.myProp == true;
    });
}
Run Code Online (Sandbox Code Playgroud)


exe*_*ook 5

您的问题不是 forEach 是异步的,因为它不是。但因为你把一个回报误认为是另一个回报。

true从回调返回,而不是从主函数返回。

forEach 之所以称为 forEach 是因为它针对数组上的每个元素执行,不能在中间停止。这是文档的摘录:

注意:无法停止或中断 forEach 循环。解决方案是使用 Array.every 或 Array.some。


dav*_*ave 2

问题是您从内部函数返回true 值,但没有在外部函数中捕获它。如果你这样做,它应该可以工作:

var retVal = false;
data.forEach(function (elm) {
    if (elm.myProp == true) {
        retVal = true;
    }
});
return retVal;
Run Code Online (Sandbox Code Playgroud)

现在你有两个功能:

var analyze_data = ***function (data)*** {
  data.forEach(***function (elm)*** {
    if (elm.myProp == true) {
        return true; //returns out of function(elm)
    }
  });
  //the true value is gone - you didn't do anything with it
  return false; //always returns false out of function(data)
}
Run Code Online (Sandbox Code Playgroud)

编辑:

data.forEach(function (elm) {
    if (elm.myProp == true) {
        resolve(elm);
    }
});
resolve(false);
Run Code Online (Sandbox Code Playgroud)

你现在(可能)决定要解决elm,但之后总是要解决false。我不能 100% 确定这种行为,但我猜后面的行为会覆盖第一个行为。因此,您需要再次检查:

is_found = false;
data.forEach(function (elm) {
    if (elm.myProp == true) {
        resolve(elm);
        is_found = true;
    }
});
if (!is_found) {
    resolve(false);
}
Run Code Online (Sandbox Code Playgroud)

当然,你似乎应该这样做:

if (!is_found) {
   reject(false);
}
Run Code Online (Sandbox Code Playgroud)

那么你可以这样做:

promise.then(function(result) {
    // do stuff since it found stuff :)
}, function(err) {
    // do stuff since if didn't find anything :(
});
Run Code Online (Sandbox Code Playgroud)