I am new to Nodejs and javascript developmnet. I recently came across promises and I was wondering how I could get over an issue I was facing.
Here is my code:
for (let j = 0; j < expired_vals.length; j++) {
var data = {
'customer-id': expired_vals[j].customer,
'sound-id': expired_vals[j].id
};
console.log(data)
getDatabaseTemporaryURL(data).then(function(url) {
console.log(data)
if(url) {
//do stuff with url
}
});
}
In the code above the first console.log returns the proper value of datas,
{ 'customer-id': 1, 'sound-id': 245 }
{ 'customer-id': 1, 'sound-id': 246 }
{ 'customer-id': 1, 'sound-id': 247 }
{ 'customer-id': 1, 'sound-id': 248 }
{ 'customer-id': 1, 'sound-id': 249 }
In the second log I only get the last value repeated,
{ 'customer-id': 1, 'sound-id': 249 }
{ 'customer-id': 1, 'sound-id': 249 }
{ 'customer-id': 1, 'sound-id': 249 }
{ 'customer-id': 1, 'sound-id': 249 }
{ 'customer-id': 1, 'sound-id': 249 }
I know that this is an issue with my promise chain since getDatabaseTemporaryURL is a promise function.
function getTemporaryURL({ data }) {
const customer_id = data['customer-id'];
const sound_id = data['sound-id'];
return new Promise((resolve, reject) => {
//get presigned url
//do stuff and resolve
});
}
How can I modify my code so that I can access each correct iteration of data within the .then of getDatabaseTemporaryURL? Or should I move to an async/await situation?
Let me know! Any help would be much appreciated!
Two things cause this:
var
creates a function scoped variable.then()
is called AFTER the entire loop is done so, all your .then()
handlers will only log the last value that your data
variable had.Here's some more detail. When you use:
var data = {...};
That creates a single variable with function scope. Subsequent iterations of the loop just assign to that variable, they don't create a new one. So, all your iterations of the loop are using the same variable.
It is equivalent to this:
var data;
for (let j = 0; j < expired_vals.length; j++) {
data = {
'customer-id': expired_vals[j].customer,
'sound-id': expired_vals[j].id
};
console.log(data)
getDatabaseTemporaryURL(data).then(function(url) {
console.log(data)
if(url) {
//do stuff with url
}
});
}
Then, since .then()
handlers are always called asynchronously after the current Javascript context finishes executing, that means that your for
loop will finish executing before any of your .then()
handlers are called. So, when you console.log(data)
inside the .then()
handler, all you will see is the last value that you assigned to data
in your loop - the value you assigned on the last iteration of the for
loop.
If you want each .then()
to log the value of the data
variable for its own iteration of the for
loop, then use let
instead of var
.
for (let j = 0; j < expired_vals.length; j++) {
let data = {
'customer-id': expired_vals[j].customer,
'sound-id': expired_vals[j].id
};
console.log(data)
getDatabaseTemporaryURL(data).then(function(url) {
console.log(data)
if(url) {
//do stuff with url
}
});
}
This will create a separate data
variable for each iteration of the loop. let
gives the variable block scope so that the data
variable has loop scope, not function scope.
FYI, you should pretty much never be using var
any more. Use let
or const
. You can always put a let
definition at the top of your function if you really want a function-scoped variable. Otherwise, you can more precisely control the scope of your variables with const
and let
which is always a good thing.