Variable scope problem in foreach loop - Nodejs

Asked

Viewed 336 times

0

I’m trying to get back to the view ejs home/index the vector of objects objArray, but when exiting the foreach loop and doing all processing of the data I am receiving from the bank the objArray returns empty.

Follow the code below

const model = require('../../models/home');

module.exports.index = async (app, req, res) => {
    let obj = {
        id_gt: 0,
        id_membro: 0,
        nome: '',
        escola: '',
        presenca: 0,
    };

    let objArray = [];

    let membros = await model.getMembro();

    membros.forEach(async membro => {
        let  presenca = await model.getPresenca(membro.id_membro);
        obj = {...membro, presenca: geraPresenca(presenca)}
        objArray = [...objArray, obj];
        //#1 console.log(objArray) retorna todo o vetor durante o loop
    });

    console.log(objArray); //#2 retorna = []
    res.render('home/index', {objArray});
}

As I highlighted in the code, in #1 the code returns all objects within the array, but in #2, when exiting the loop, the function log returns an empty array.

How can I get to "see" these changes made in foreach and be able to return to the view this my array with all objects?

I read in some articles that I may be working with Closure, but I still can’t generate a solution.

If anyone can help me with that, I’d appreciate it!!

  • forEach does not work with asynchronous functions. Probably your problem comes from there.

2 answers

0


The problem has been solved?

Even using async in the callback of forEach, your code will only wait during the await internally in the callback. That is, the forEach awaits the answer, but its code does not wait for the forEach.

Usually to wait for the answer of several items, you can use Promise.all or for await (item of itens), as an example:

let membros = await model.getMembro();

// crio um array de promises, as respostas estão empacotadas dentro das promises, 
// eu tenho que esperar pela resolução das promises para desempacotar as respostas
let promisePresencas = membros.map(membro => model.getPresenca(membro.id_membro));

// este método recebe um array de promises, e retorna uma única promise
// empacotando todo o array, agora eu posso utilizar o await
let presencas = await Promise.all(promisePresencas);

let objArray = membros.map((membro, i) => ({ ...membro, presenca: gerarPresenca(presencas[i]) }));

res.render('home/index', {objArray});

Or with a bow for:

let objArray = [];
let membros = await model.getMembro();

// mesmo processo
let promisePresencas = membros.map(membro => model.getPresenca(membro.id_membro));

let i = 0;
for await (let presenca of promisePresencas) {
    objArray.push({ ...membros[i++], presenca: gerarPresenca(presenca) });
}

res.render('home/index', {objArray});

0

Just don’t use foreach. Usa for (Let member of members) {}.

That:

membros.forEach(async membro => {
   let  presenca = await model.getPresenca(membro.id_membro);
   obj = {...membro, presenca: geraPresenca(presenca)}
   objArray = [...objArray, obj];
   //#1 console.log(objArray) retorna todo o vetor durante o loop
});

That’s why:

for (let membro of membros) {
   let  presenca = await model.getPresenca(membro.id_membro);
   obj = {...membro, presenca: geraPresenca(presenca)}
   objArray = [...objArray, obj];
   //#1 console.log(objArray) retorna todo o vetor durante o loop
}
  • That your solution worked too! Thank you

Browser other questions tagged

You are not signed in. Login or sign up in order to post.