Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

486
Visualizações
Nodo JS Promise.all y forEach

Tengo una estructura similar a una matriz que expone métodos asíncronos. Las llamadas al método asíncrono devuelven estructuras de matriz que, a su vez, exponen más métodos asíncronos. Estoy creando otro objeto JSON para almacenar los valores obtenidos de esta estructura, por lo que debo tener cuidado al realizar un seguimiento de las referencias en las devoluciones de llamada.

He codificado una solución de fuerza bruta, pero me gustaría aprender una solución más idiomática o limpia.

  1. El patrón debe ser repetible para n niveles de anidamiento.
  2. Necesito usar promise.all o alguna técnica similar para determinar cuándo resolver la rutina adjunta.
  3. No todos los elementos implicarán necesariamente realizar una llamada asíncrona. Entonces, en una promesa anidada, no puedo simplemente hacer asignaciones a los elementos de mi matriz JSON en función del índice. Sin embargo, necesito usar algo como promise.all en forEach anidado para garantizar que todas las asignaciones de propiedades se hayan realizado antes de resolver la rutina adjunta.
  4. Estoy usando bluebird promise lib pero esto no es un requisito

Aquí hay un código parcial:

 var jsonItems = []; items.forEach(function(item){ var jsonItem = {}; jsonItem.name = item.name; item.getThings().then(function(things){ // or Promise.all(allItemGetThingCalls, function(things){ things.forEach(function(thing, index){ jsonItems[index].thingName = thing.name; if(thing.type === 'file'){ thing.getFile().then(function(file){ //or promise.all? jsonItems[index].filesize = file.getSize();
over 4 years ago · Santiago Trujillo
3 Respostas
Responde à pergunta

0

Es bastante sencillo con algunas reglas simples:

  • Siempre que cree una promesa en un then , devuélvala : cualquier promesa que no devuelva no se esperará fuera.
  • Cada vez que crea varias promesas, .all ellas : de esa manera espera a que se silencien todas las promesas y ningún error de ninguna de ellas.
  • Cada vez que anida then s, generalmente puede regresar en el medio ; then , las cadenas generalmente tienen como máximo 1 nivel de profundidad.
  • Cada vez que realice IO, debe ser con una promesa , o debe estar en una promesa o debe usar una promesa para señalar su finalización.

Y algunos consejos:

  • La asignación se realiza mejor con .map que con for/push : si está asignando valores con una función, map le permite expresar de manera concisa la noción de aplicar acciones una por una y agregar los resultados.
  • La simultaneidad es mejor que la ejecución secuencial si es gratis : es mejor ejecutar las cosas al mismo tiempo y esperarlas Promise.all que ejecutar las cosas una tras otra, cada una esperando antes de la siguiente.

Bien, empecemos:

 var items = [1, 2, 3, 4, 5]; var fn = function asyncMultiplyBy2(v){ // sample async action return new Promise(resolve => setTimeout(() => resolve(v * 2), 100)); }; // map over forEach since it returns var actions = items.map(fn); // run the function over all items // we now have a promises array and we want to wait for it var results = Promise.all(actions); // pass array of promises results.then(data => // or just .then(console.log) console.log(data) // [2, 4, 6, 8, 10] ); // we can nest this of course, as I said, `then` chains: var res2 = Promise.all([1, 2, 3, 4, 5].map(fn)).then( data => Promise.all(data.map(fn)) ).then(function(data){ // the next `then` is executed after the promise has returned from the previous // `then` fulfilled, in this case it's an aggregate promise because of // the `.all` return Promise.all(data.map(fn)); }).then(function(data){ // just for good measure return Promise.all(data.map(fn)); }); // now to get the results: res2.then(function(data){ console.log(data); // [16, 32, 48, 64, 80] });
over 4 years ago · Santiago Trujillo Relatório

0

Aquí hay un ejemplo simple usando reduce. Se ejecuta en serie, mantiene el orden de inserción y no requiere Bluebird.

 /** * * @param items An array of items. * @param fn A function that accepts an item from the array and returns a promise. * @returns {Promise} */ function forEachPromise(items, fn) { return items.reduce(function (promise, item) { return promise.then(function () { return fn(item); }); }, Promise.resolve()); }

Y utilízalo así:

 var items = ['a', 'b', 'c']; function logItem(item) { return new Promise((resolve, reject) => { process.nextTick(() => { console.log(item); resolve(); }) }); } forEachPromise(items, logItem).then(() => { console.log('done'); });

Hemos encontrado útil enviar un contexto opcional en bucle. El contexto es opcional y compartido por todas las iteraciones.

 function forEachPromise(items, fn, context) { return items.reduce(function (promise, item) { return promise.then(function () { return fn(item, context); }); }, Promise.resolve()); }

Su función de promesa se vería así:

 function logItem(item, context) { return new Promise((resolve, reject) => { process.nextTick(() => { console.log(item); context.itemCount++; resolve(); }) }); }
over 4 years ago · Santiago Trujillo Relatório

0

Tuve a través de la misma situación. Lo resolví usando dos Promise.All().

Creo que fue una solución realmente buena, así que la publiqué en npm: https://www.npmjs.com/package/promise-foreach

Creo que tu código será algo como esto.

 var promiseForeach = require('promise-foreach') var jsonItems = []; promiseForeach.each(jsonItems, [function (jsonItems){ return new Promise(function(resolve, reject){ if(jsonItems.type === 'file'){ jsonItems.getFile().then(function(file){ //or promise.all? resolve(file.getSize()) }) } }) }], function (result, current) { return { type: current.type, size: jsonItems.result[0] } }, function (err, newList) { if (err) { console.error(err) return; } console.log('new jsonItems : ', newList) })
over 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda