如何停止Javascript forEach?

发布于 2024-11-14 08:19:38 字数 429 浏览 5 评论 0原文

我正在使用 Node.js 和 Mongoose - 尝试在嵌套有递归函数和 forEach 的深层注释中找到特定注释。有没有办法停止 Node.js forEach?据我了解,每个 forEach 迭代都是一个函数,我不能只执行 break,只能执行 return 但这不会停止 forEach

function recurs(comment) {
    comment.comments.forEach(function(elem) {

        recurs(elem);

        //if(...) break;

    });
}

I'm playing with Node.js and Mongoose — trying to find specific comment in deep comments nesting with recursive function and forEach within. Is there a way to stop Node.js forEach? As I understand every forEach iteration is a function and and I can't just do break, only return but this won't stop forEach.

function recurs(comment) {
    comment.comments.forEach(function(elem) {

        recurs(elem);

        //if(...) break;

    });
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(13

偷得浮生 2024-11-21 08:19:38

您无法脱离 forEach。不过,我可以想到三种方法来伪造它。

1.丑陋的方式:将第二个参数传递给 forEach用作上下文,并在其中存储一个布尔值,然后使用 if。这看起来很糟糕。

2.有争议的方式:将整个事情包围在 try-catch 块中,并在想要中断时抛出异常。这看起来很糟糕,可能会影响性能,但可以封装。

3.有趣的方式:使用 every()

['a', 'b', 'c'].every(function(element, index) {
  // Do your thing, then:
  if (you_want_to_break) return false
  else return true
})

您可以使用 some( ) 相反,如果您希望返回 true 来中断。

You can't break from a forEach. I can think of three ways to fake it, though.

1. The Ugly Way: pass a second argument to forEach to use as context, and store a boolean in there, then use an if. This looks awful.

2. The Controversial Way: surround the whole thing in a try-catch block and throw an exception when you want to break. This looks pretty bad and may affect performance, but can be encapsulated.

3. The Fun Way: use every().

['a', 'b', 'c'].every(function(element, index) {
  // Do your thing, then:
  if (you_want_to_break) return false
  else return true
})

You can use some() instead, if you'd rather return true to break.

北座城市 2024-11-21 08:19:38

突破 Array#forEach 是不可能的。 (您可以在链接页面上检查在 Firefox 中实现它的源代码,以确认这一点。)

相反,您应该使用普通的 for 循环:(

function recurs(comment) {
    for (var i = 0; i < comment.comments.length; ++i) {
        var subComment = comment.comments[i];
        recurs(subComment);
        if (...) {
            break;
        }
    }
}

或者,如果您想更聪明一点关于它, comment.comments[i] 始终是一个对象:)

function recurs(comment) {
    for (var i = 0, subComment; subComment = comment.comments[i]; ++i) {
        recurs(subComment);
        if (...) {
            break;
        }
    }
}

Breaking out of Array#forEach is not possible. (You can inspect the source code that implements it in Firefox on the linked page, to confirm this.)

Instead you should use a normal for loop:

function recurs(comment) {
    for (var i = 0; i < comment.comments.length; ++i) {
        var subComment = comment.comments[i];
        recurs(subComment);
        if (...) {
            break;
        }
    }
}

(or, if you want to be a little more clever about it and comment.comments[i] is always an object:)

function recurs(comment) {
    for (var i = 0, subComment; subComment = comment.comments[i]; ++i) {
        recurs(subComment);
        if (...) {
            break;
        }
    }
}
心房的律动 2024-11-21 08:19:38

forEach 在返回时不会中断,有一些丑陋的解决方案可以完成这项工作,但我建议不要使用它,而是尝试使用 Array.prototype.some 或 Array.prototype.every代码>

var ar = [1,2,3,4,5];

ar.some(function(item,index){
  if(item == 3){
     return true;
  }
  console.log("item is :"+item+" index is : "+index);
});

forEach does not break on return, there are ugly solutions to get this work but I suggest not to use it, instead try to use Array.prototype.some or Array.prototype.every

var ar = [1,2,3,4,5];

ar.some(function(item,index){
  if(item == 3){
     return true;
  }
  console.log("item is :"+item+" index is : "+index);
});

狂之美人 2024-11-21 08:19:38

在某些情况下 Array.some 可能会满足要求。

In some cases Array.some will probably fulfil the requirements.

∝单色的世界 2024-11-21 08:19:38

正如其他人指出的那样,您无法取消 forEach 循环,但这是我的解决方案:

ary.forEach(function loop(){
    if(loop.stop){ return; }

    if(condition){ loop.stop = true; }
});

当然,这实际上并没有打破循环,它只是阻止了“后面的所有元素上的代码执行”休息”

As others have pointed out, you can't cancel a forEach loop, but here's my solution:

ary.forEach(function loop(){
    if(loop.stop){ return; }

    if(condition){ loop.stop = true; }
});

Of course this doesn't actually break the loop, it just prevents code execution on all the elements following the "break"

如梦亦如幻 2024-11-21 08:19:38

我猜你想使用 Array.prototype。find
当 Find 在数组中找到您的特定值时,它会自行中断。

var inventory = [
  {name: 'apples', quantity: 2},
  {name: 'bananas', quantity: 0},
  {name: 'cherries', quantity: 5}
];

function findCherries(fruit) { 
  return fruit.name === 'cherries';
}

console.log(inventory.find(findCherries)); 
// { name: 'cherries', quantity: 5 }

I guess you want to use Array.prototype.find
Find will break itself when it finds your specific value in the array.

var inventory = [
  {name: 'apples', quantity: 2},
  {name: 'bananas', quantity: 0},
  {name: 'cherries', quantity: 5}
];

function findCherries(fruit) { 
  return fruit.name === 'cherries';
}

console.log(inventory.find(findCherries)); 
// { name: 'cherries', quantity: 5 }
两个我 2024-11-21 08:19:38

如果您不介意,可以使用 Lodash 的 forEach 函数使用第三方库。

例子:

var _ = require('lodash');

_.forEach(comments, function (comment) {
    do_something_with(comment);

    if (...) {
        return false;     // Exits the loop.
    }
})

You can use Lodash's forEach function if you don't mind using 3rd party libraries.

Example:

var _ = require('lodash');

_.forEach(comments, function (comment) {
    do_something_with(comment);

    if (...) {
        return false;     // Exits the loop.
    }
})
只为守护你 2024-11-21 08:19:38
    var f = "how to stop Javascript forEach?".split(' ');
    f.forEach(function (a,b){
        console.info(b+1);
        if (a == 'stop') {
            console.warn("\tposition: \'stop\'["+(b+1)+"] \r\n\tall length: " + (f.length)); 
            f.length = 0; //<--!!!
        }
    });
    var f = "how to stop Javascript forEach?".split(' ');
    f.forEach(function (a,b){
        console.info(b+1);
        if (a == 'stop') {
            console.warn("\tposition: \'stop\'["+(b+1)+"] \r\n\tall length: " + (f.length)); 
            f.length = 0; //<--!!!
        }
    });
雨巷深深 2024-11-21 08:19:38

Array.forEach 不能被破坏并使用 try...catch 或 hacky 方法,例如 Array.everyArray.some< /code> 只会让你的代码更难理解。这个问题只有两种解决方案:

1)使用旧的 for 循环:这将是最兼容的解决方案,但在大代码块中经常使用时可能很难阅读:

var testArray = ['a', 'b', 'c'];
for (var key = 0; key < testArray.length; key++) {
    var value = testArray[key];
    console.log(key); // This is the key;
    console.log(value); // This is the value;
}

2)使用在兼容性不成问题的情况下,使用新的 ECMA6(2015 规范)。请注意,即使在 2016 年,也只有少数浏览器和 IDE 为这一新规范提供良好支持。虽然这适用于可迭代对象(例如数组),但如果您想在不可迭代对象上使用它,则需要使用 Object.entries 方法。截至 2016 年 6 月 18 日,此方法几乎不可用,甚至 Chrome 也需要特殊标志才能启用它:chrome://flags/#enable-javascript-harmony。对于数组,您不需要所有这些,但兼容性仍然是一个问题:

var testArray = ['a', 'b', 'c'];
for (let [key, value] of testArray.entries()) {
    console.log(key); // This is the key;
    console.log(value); // This is the value;
}

3)很多人都会同意第一个或第二个选项都不是好的候选者。在选项 2 成为新标准之前,大多数流行的库(例如 AngularJS 和 jQuery)都会提供自己的循环方法,这些方法优于 JavaScript 中可用的任何方法。对于那些还没有使用这些大型库并且正在寻找轻量级选项的人来说,像 this 这样的解决方案可以被使用并且几乎与 ECMA6 相当,同时保持与旧浏览器的兼容性。

Array.forEach cannot be broken and using try...catch or hacky methods such as Array.every or Array.some will only make your code harder to understand. There are only two solutions of this problem:

1) use a old for loop: this will be the most compatible solution but can be very hard to read when used often in large blocks of code:

var testArray = ['a', 'b', 'c'];
for (var key = 0; key < testArray.length; key++) {
    var value = testArray[key];
    console.log(key); // This is the key;
    console.log(value); // This is the value;
}

2) use the new ECMA6 (2015 specification) in cases where compatibility is not a problem. Note that even in 2016, only a few browsers and IDEs offer good support for this new specification. While this works for iterable objects (e.g. Arrays), if you want to use this on non-iterable objects, you will need to use the Object.entries method. This method is scarcely available as of June 18th 2016 and even Chrome requires a special flag to enable it: chrome://flags/#enable-javascript-harmony. For Arrays, you won't need all this but compatibility remains a problem:

var testArray = ['a', 'b', 'c'];
for (let [key, value] of testArray.entries()) {
    console.log(key); // This is the key;
    console.log(value); // This is the value;
}

3) A lot of people would agree that neither the first or second option are good candidates. Until option 2 becomes the new standard, most popular libraries such as AngularJS and jQuery offer their own loop methods which can be superior to anything available in JavaScript. Also for those who are not already using these big libraries and that are looking for lightweight options, solutions like this can be used and will almost be on par with ECMA6 while keeping compatibility with older browsers.

疯狂的代价 2024-11-21 08:19:38

一旦满足条件,下面的代码将中断 foreach 循环,下面是示例

    var array = [1,2,3,4,5];
    var newArray = array.slice(0,array.length);
    array.forEach(function(item,index){
        //your breaking condition goes here example checking for value 2
        if(item == 2){
            array.length = array.indexOf(item);
        }

    })
    array = newArray;

Below code will break the foreach loop once the condition is met, below is the sample example

    var array = [1,2,3,4,5];
    var newArray = array.slice(0,array.length);
    array.forEach(function(item,index){
        //your breaking condition goes here example checking for value 2
        if(item == 2){
            array.length = array.indexOf(item);
        }

    })
    array = newArray;
无需解释 2024-11-21 08:19:38

如果您覆盖 Array 方法,则可以从 forEach 循环中中断:

(function(){
    window.broken = false;

        Array.prototype.forEach = function(cb, thisArg) {
            var newCb = new Function("with({_break: function(){window.broken = true;}}){("+cb.replace(/break/g, "_break()")+"(arguments[0], arguments[1], arguments[2]));}");
            this.some(function(item, index, array){
                 newCb(item, index, array);
                 return window.broken;
            }, thisArg);
            window.broken = false;
        }

}())

示例:

[1,2,3].forEach("function(x){\
    if (x == 2) break;\
    console.log(x)\
}")

不幸的是,使用此解决方案,您不能在回调中使用正常的中断,您必须将无效代码包装在字符串中,并且本机函数不能直接工作(但您可以解决这个问题)

快乐打破!

You can break from a forEach loop if you overwrite the Array method:

(function(){
    window.broken = false;

        Array.prototype.forEach = function(cb, thisArg) {
            var newCb = new Function("with({_break: function(){window.broken = true;}}){("+cb.replace(/break/g, "_break()")+"(arguments[0], arguments[1], arguments[2]));}");
            this.some(function(item, index, array){
                 newCb(item, index, array);
                 return window.broken;
            }, thisArg);
            window.broken = false;
        }

}())

example:

[1,2,3].forEach("function(x){\
    if (x == 2) break;\
    console.log(x)\
}")

Unfortunately with this solution you can't use normal break inside your callbacks, you must wrap invalid code in strings and native functions don't work directly (but you can work around that)

Happy breaking!

瀞厅☆埖开 2024-11-21 08:19:38

为什么不使用简单的返回?

function recurs(comment){
comment.comments.forEach(function(elem){
    recurs(elem);
    if(...) return;
});

它将从“recurs”函数返回。我这样用。尽管这不会破坏 forEach 而是破坏整个函数,但在这个简单的示例中它可能会起作用

Wy not use plain return?

function recurs(comment){
comment.comments.forEach(function(elem){
    recurs(elem);
    if(...) return;
});

it will return from 'recurs' function. I use it like this. Althougth this will not break from forEach but from whole function, in this simple example it might work

九厘米的零° 2024-11-21 08:19:38

jQuery 提供了each() 方法,而不是forEach() 方法。您可以通过返回 false 来打破 each。 forEach() 是 ECMA-262 标准的一部分,据我所知,打破该标准的唯一方法是抛出异常。

function recurs(comment) {
  try {
    comment.comments.forEach(function(elem) {
      recurs(elem);
      if (...) throw "done";
    });
  } catch (e) { if (e != "done") throw e; }
}

丑陋,但能胜任工作。

jQuery provides an each() method, not forEach(). You can break out of each by returning false. forEach() is part of the ECMA-262 standard, and the only way to break out of that that I'm aware of is by throwing an exception.

function recurs(comment) {
  try {
    comment.comments.forEach(function(elem) {
      recurs(elem);
      if (...) throw "done";
    });
  } catch (e) { if (e != "done") throw e; }
}

Ugly, but does the job.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文