I'm making an async call (https://github.com/socketio/socket.io-redis#redisadapterclientsroomsarray-fnfunction) with socket.io inside of a loop.
elements.forEach((element) => {
const foo = {
id: element.id,
name: element.name,
};
// async code
io.in(element.id).clients((err, clients) => {
foo.clients = clients;
});
});
Since this loop will run to completion before all the async calls complete, is there a guarantee that callback function will use the const foo declared immediately before it?
is there a guarantee that callback function will use the
const foodeclared immediately before it
TL; DR; Yes.
The reference to socket.io is irrelevant. The guarantee comes from JS itself.
Each time
const foo = { ... }
and
(err, clients) => { foo.clients = clients })
executed they're not simple declaring a variable and a function, but create a new variable and a new closure.
Probably your fears come from the common pitfall of var:
for(var i = 0 ; i != 3 ; ++i) setTimeout(() => console.log("i =", i), 0)
this will output "i = 3" tree times.
But any of the following will give you the expected result:
let/const:
for(let i = 0 ; i != 3 ; ++i) setTimeout(() => console.log("i =", i), 0)
That's because let (and const) behaves differently from var. See MDN:
letallows you to declare variables that are limited to the scope of a block statement, or expression on which it is used, unlike thevarkeyword, which defines a variable globally, or locally to an entire function regardless of block scope
forEach:
[1,2,3].forEach((v, i) => setTimeout(() => console.log("i =", i), 0) )
That's because arguments of each call of forEach callback are actually different variables
And even var inside a function scope:
[1,2,3].forEach((v, i_) => { var i = i_; setTimeout(() => console.log("i =", i), 0) } )
That's because var i = i_ declares a new variable local to each call of forEach callback.
But it's not so in this case:
for(let i_ = 0 ; i_ != 3 ; ++i_) {
var i = i_
setTimeout(() => console.log("i =", i), 0)
}
Because var is hoisted. So the previous code is equivalent to
var i
for(let i_ = 0 ; i_ != 3 ; ++i_) {
i = i_
setTimeout(() => console.log("i =", i), 0)
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With