es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

La función async / await / forEach no espera la respuesta.

async function updateJSON(originalJSON, assetsArr) {
  Object.keys(originalJSON).forEach(key => {originalJSON[key].active = false}); // reiniciar todos los registros
  Object.keys(assetsArr).forEach(async key => {
    let idx = originalJSON.findIndex(x => x.name === assetsArr[key].name);
    if (idx === -1) { // no coincidencia -> insertar un nuevo registro
      const codeNr = await getCode(assetsArr[key].tokenId);
      let debug = originalJSON.push({ name: assetsArr[key].name, active: true, code: codeNr });
      console.log("La longitud de la lista ahora es:", debug);
    } else { originalJSON[idx].active = true; } // hay coincidencia, así que actualiza el registro existente para que sea 'activo'
  });
  return originalJSON;
}

console.table(await updateJSON(originalJSON, assetsArr));

No puedo encontrar una manera para que el código espere a que await getCode termine antes de devolver la función. Obtiene una ejecución parcial de inmediato y solo entonces el código relacionado con originalJSON.push se ejecuta uno a uno.

Si elimino async en la línea 3 y await en la línea 6, la función se ejecuta secuencialmente (sincrónicamente?), excepto que obtengo “Promise { }” en lugar del número de código que la función getCode debe recuperar. Este número proviene de una llamada a URL fetch().

Leí Async/Await not waiting y creo que mi problema está relacionado. ¿Debo usar map() en lugar de forEach()? Encuentro map() confuso. Quiero mutar el array, no estoy interesado en crear uno nuevo (aunque lo haré si eso es lo que solucionará esto).

Tags:  , , ,

Answer

  1. Avatar for davy.ai

    El problema con el código es que forEach() no espera que las operaciones asíncronas se completen antes de pasar al siguiente elemento en el array. Esto significa que la función getCode() no puede completarse antes de pasar a la siguiente iteración del bucle.

    Una solución a este problema es usar un bucle for...of en lugar de forEach(), ya que for...of espera a que cada iteración se complete antes de pasar a la siguiente. Otra solución es usar Promise.all() para esperar a que todas las operaciones asíncronas se completen antes de devolver el JSON actualizado.

    Aquí tienes un ejemplo de cómo usar Promise.all() en el código:

    async function updateJSON(original_JSON, assets_arr) {
      Object.keys(original_JSON).forEach(key => {original_JSON[key].active = false}); // restablecer todos los registros
      const updatedRecords = await Promise.all(Object.keys(assets_arr).map(async key => {
        let idx = original_JSON.findIndex(x => x.name === assets_arr[key].name);
        if (idx === -1) { // no hay coincidencia -> insertar un nuevo registro
          const code_nr = await getCode(assets_arr[key].token_id);
          const updatedRecord = { name: assets_arr[key].name, active: true, code: code_nr };
          console.log("Nuevo registro:", updatedRecord);
          return updatedRecord;
        } else {
          original_JSON[idx].active = true; // hay una coincidencia, así que solo actualiza el registro existente para que sea 'activo'
          return original_JSON[idx];
        }
      }));
      return updatedRecords;
    }
    
    console.table(await updateJSON(original_JSON, assets_arr));
    

    En este ejemplo, Promise.all() se utiliza para esperar a que todas las promesas devueltas por la función map() se resuelvan antes de devolver los registros actualizados. La función map() se utiliza para crear un array de promesas que se resuelven en los registros actualizados.

Comments are closed.