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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/26678379/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-22 23:13:39  来源:igfitidea点击:

Synchronous forEach loop (wait for it to end)

javascriptnode.jsforeachsynchronous

提问by apparatix

I have a function in Node.js that takes in an array and loops through it, doing somewhat time-consuming computations on each element.

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

Here's a super-simplified version of the function:

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

var analyze_data = function (data) {
    data.forEach(function (elm) {
        if (elm.myProp == true) {
            return true;
        }
    });
    return false;
}

Essentially, I want the function to return true if any of the elements' property myPropis equal to true. If none of the elements satisfy this condition, the function should return false.

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

However, the code never waits for the forEach loop to finish. In other words, if the 100th element in the array satisfies the condition, the function should return true. Instead, it skips to return false;and returns false before the forEachloop has time to finish.

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

Is there a solution to this?

这个问题有方法解决吗?

Edit

编辑

So I realized that I oversimplified my question - I'm actually using the Node.js package es6-promise, and my code looks more like this:

所以我意识到我过于简化了我的问题——我实际上使用的是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);
    });
}

So in reality, I don't have the issue of returning a value in the forEach function rather than the outer function. Additionally, notice how the function resolves to the element itself rather than true, otherwise false. I actually want to return some relevant data if the one of the elements passes the condition, otherwise false to indicate that they all failed.

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

Any ideas now? :p Also, thanks for all the original answers!

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

回答by manji

It is not a question of sync/async execution. What you are doing is returning true in the for each callback (which is invisible for your analyze_datafunction), then returning false after forEach is finished.

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

You need to use Array.prototype.some:

您需要使用Array.prototype.some

var analyze_data = function (data) {
    return data.some(function (elm) {
        return elm.myProp == true;
    });
}

回答by exebook

Your problem is not the fact that forEach is async, because it is not. But because you mistake one return for another.

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

You return truefrom callback not from your main function.

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

forEach called forEach because it executes for each element on the array, you can't stop in the middle. Here is the excerpt from documentation:

forEach 调用 forEach 是因为它对数组中的每个元素都执行,你不能中途停下来。以下是文档的摘录:

Note: There is no way to stop or break a forEach loop. The solution is to use Array.every or Array.some.

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

回答by dave

The issue is that you are returning from your inner functionthe value of true, but not capturing it in the outer function. If you do it like this it should work:

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

var retVal = false;
data.forEach(function (elm) {
    if (elm.myProp == true) {
        retVal = true;
    }
});
return retVal;

Right now you have two functions:

现在你有两个功能:

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)
}

EDIT:

编辑:

data.forEach(function (elm) {
    if (elm.myProp == true) {
        resolve(elm);
    }
});
resolve(false);

You now are (possibly) resolving to elm, but ALWAYS after that resolving to false. I'm not 100% sure on the behaviour, but I would guess that the later one overwrites the first one. So again, you need to check:

您现在(可能)正在解析为elm,但始终在解析为false. 我对这种行为不是 100% 确定,但我猜后一个会覆盖第一个。因此,您需要再次检查:

is_found = false;
data.forEach(function (elm) {
    if (elm.myProp == true) {
        resolve(elm);
        is_found = true;
    }
});
if (!is_found) {
    resolve(false);
}

Of course, it kind of seems like you should be doing:

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

if (!is_found) {
   reject(false);
}

So then you can do:

那么你可以这样做:

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