cómo detener Javascript forEach? [duplicar]


Esta pregunta ya tiene una respuesta aquí:

Estoy jugando con nodejs y mangosta - tratando de encontrar comentario específico en comentarios profundos anidando con recursivo func y foreach dentro. ¿Hay alguna manera de detener a Nodejs forEach? Como entiendo cada iteración forEach es una función y y no puedo simplemente hacer "break", solo" return " pero esto no se detendrá foreach.

function recurs(comment){
    comment.comments.forEach(function(elem){
        recurs(elem);
        //if(...) break;
    });
}
Author: Charles, 2011-06-07

13 answers

No puedes romper con un forEach. Se me ocurren tres formas de fingirlo.

1. The Ugly Way : pase un segundo argumento a forEach a use como contexto, y almacene un booleano allí, luego use un if. Esto se ve horrible.

2. La Forma Controvertida : rodear todo en un bloque try-catch y lanzar una excepción cuando se quiere romper. Esto se ve bastante mal y puede afectar el rendimiento, pero se puede encapsular.

3. La Manera Divertida : usar every().

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

Puede utilizar some() en cambio, si prefieres return true romper.

 702
Author: slezica,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-07-05 19:44:14

La ruptura de Array#forEach no es posible. (Puede inspeccionar el código fuente que lo implementa en Firefox en la página vinculada, para confirmar esto.)

En su lugar, debe usar un bucle for normal:

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

(o, si quieres ser un poco más inteligente al respecto y comment.comments[i] siempre es un objeto:)

function recurs(comment) {
    for (var i = 0, subComment; subComment = comment.comments[i]; ++i) {
        recurs(subComment);
        if (...) {
            break;
        }
    }
}
 36
Author: Domenic,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-06-07 05:12:49

Como otros han señalado, no se puede cancelar un bucle forEach, pero aquí está mi solución:

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

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

Por supuesto, esto no rompe el bucle, solo evita la ejecución de código en todos los elementos que siguen al "break"

 29
Author: Mark Kahn,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-06-07 05:26:00

En algunos casos Array.some probablemente cumpla los requisitos.

 28
Author: igor,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-05-14 17:15:52

Supongo que quieres usar Array.prototipo.buscar Find se romperá cuando encuentre su valor específico en la matriz.

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 }
 8
Author: Shrihari Balasubramani,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-07-11 07:02:36

Puedes usar Lodash's forEach función si no le importa usar bibliotecas de terceros.

Ejemplo:

var _ = require('lodash');

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

    if (...) {
        return false;     // Exits the loop.
    }
})
 5
Author: exmaxx,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-10-21 12:17: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; //<--!!!
        }
    });
 3
Author: Владимир,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-01-10 12:24:30

Array.forEach no se puede romper y usar try...catch o métodos hacky como Array.every o Array.some solo hará que su código sea más difícil de entender. Hay solo dos soluciones de este problema:

1) use un bucle for antiguo: esta será la solución más compatible, pero puede ser muy difícil de leer cuando se usa a menudo en grandes bloques de código:

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) utilice la nueva ECMA6 (especificación 2015) en los casos en que la compatibilidad no sea un problema. Tenga en cuenta que incluso en 2016, solo unos pocos navegadores e IDE ofrecen buen soporte para esta nueva especificación. Si bien esto funciona para objetos iterables (por ejemplo, Arrays), si desea usar esto en objetos no iterables, necesitará usar el método Object.entries. Este método apenas está disponible a partir de junio 18th 2016 e incluso Chrome requiere una bandera especial para habilitarlo: chrome://flags/#enable-javascript-harmony. Para los arrays, no necesitará todo esto, pero la compatibilidad sigue siendo un problema:

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) Mucha gente estaría de acuerdo en que ni la primera ni la segunda opción son buenos candidatos. Hasta la opción 2 se convierte en el nuevo estándar, las bibliotecas más populares como AngularJS y jQuery ofrecen sus propios métodos de bucle que pueden ser superiores a cualquier cosa disponible en JavaScript. También para aquellos que aún no están utilizando estas grandes bibliotecas y que están buscando opciones ligeras, soluciones como this se pueden usar y casi estarán a la par con ECMA6, manteniendo la compatibilidad con navegadores más antiguos.

 3
Author: Nicolas Bouvrette,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-06-18 13:02:42

ForEach no se rompe en el retorno, hay soluciones feas para obtener este trabajo, pero sugiero no usarlo, en su lugar tratar de utilizar Array.prototype.some o 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);
});
 2
Author: imal hasaranga perera,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-08-08 04:19:44

El siguiente código romperá el bucle foreach una vez que se cumpla la condición, a continuación se muestra el ejemplo de ejemplo

    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;
 1
Author: D G ANNOJIRAO,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-06-13 04:01:01

Puede romper un bucle forEach si sobrescribe el método Array:

(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;
        }

}())

Ejemplo:

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

Desafortunadamente con esta solución no puede usar un descanso normal dentro de sus devoluciones de llamada, debe envolver código no válido en cadenas y las funciones nativas no funcionan directamente (pero puede evitar eso)

Feliz ruptura!

 -2
Author: ApplePear,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-05-16 22:23:54

¿Por qué no usar plain return?

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

Volverá desde la función 'recurs'. Lo uso así. Aunque esto no se romperá de forEach sino de toda la función, en este simple ejemplo podría funcionar

 -10
Author: user2381380,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-03-12 18:17:20

JQuery proporciona un método each(), no forEach(). Puedes salir de each devolviendo false. forEach() es parte del estándar ECMA-262, y la única manera de salir de eso que soy consciente es lanzando una excepción.

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

Feo, pero hace el trabajo.

 -15
Author: Joe Taylor,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-06-07 05:22:09