I have some problems understanding asyncronous nodejs in a loop and the associated scope I guess.
Basically, I want to extract different values and store it in a "template" object that I will implement each loop and store in an array of promises in order to use it when resolved.
It might seem (a lot) far fetched for this code's actual goal but i struggle understanding why does the promise variable is only returning the last element each loop even if i pass the index value to the function and use it in then().
Code :
(async ()=>{
let tab = ["a","b","c","d"];
let data = { name:"Random Array", data:null, idx:null};
let promise = {};
let promisesArray = [];
for(let i = 0 ; i < tab.length; i++){
promise = wait(3000).then(()=>{
let d = data;
d.data = tab[i];
d.idx = i;
d.success = true;
console.log(d);
return d;
});
promisesArray.push(promise);
}
let fullData = await Promise.all(promisesArray);
console.log(fullData);
})();
function wait(time){
return new Promise((resolve,reject)=>{
setTimeout(resolve,time)
});
}
Output :
[{ name: 'Random Array', data: 'd', idx: 3, success: true },
{ name: 'Random Array', data: 'd', idx: 3, success: true },
{ name: 'Random Array', data: 'd', idx: 3, success: true },
{ name: 'Random Array', data: 'd', idx: 3, success: true }]
Intended Output :
[{ name: 'Random Array', data: 'a', idx: 0, success: true },
{ name: 'Random Array', data: 'b', idx: 1, success: true },
{ name: 'Random Array', data: 'c', idx: 2, success: true },
{ name: 'Random Array', data: 'd', idx: 3, success: true }]
Sorry if this is some trivial knowledge but I didn't find anything about it so far. Thanks in advance for your time!
The thing is, you're using the same data
object all the time, so that's why you got 4 exactly the same objects in your array, it's all due to this line in your loop:
let d = data;
You just assign data
to d
, it doesn't make a copy of data
, but now they both have a reference to the same data
object. If you just copied the value of data
into d
you would be fine:
const d = { ...data }
// or
const d = { name:"Random Array", data:null, idx:null}
// or
const getData = () => ({ name:"Random Array", data:null, idx:null})
const d = getData()