Reputation: 473
I have a issue with a callback function's variable losing its scope
. I have the following 2 objects in an array(simplified down to show the problem)
const search = [{socket: new WebSocket('ws://live.trade/123')},
{socket: new WebSocket('ws://live.trade/xyz')}];
I then do a forEach on them in an attempt to log the sockets url once the socket is open.
search.forEach(function(element){
element.socket.on('open', function open() {
console.log(element.socket.url);
});
});
*actual output*
ws://live.trade/xyz
ws://live.trade/xyz
*expected*
ws://live.trade/123
ws://live.trade/xyz
I feel like the reason is that when the function open() runs element is not in scope and it just uses whatever was last there(being the ws://live.trade/xyz). Is this correct? And finally what would be the way to go about fixing this? The real use for this is when the socket is opened I need to send version data to the server via the socket that called it... Im going to have many sockets in reality and dont want to write a "socket.on('open'...)" for each individual one.
Any suggestions?
Thanks so much!
Upvotes: 2
Views: 213
Reputation: 399
Your callback (i.e. in socket.on()) uses the element
variable of the forEach()
. From your actual result, it could mean that:
The variable could be "overriden" over the iterations because of javascript/node scope mechanism, it is not the case with the code you gave but it is a common issue working with scopes inside loops.
in this case you would have to do :
search.forEach(function(element){
element.socket.on('open', function(){
console.log(this.socket.url);
}.bind(element));
});
Explanation:
bind()
passes its first argument (the element variable in this case) to the anonymous function as this
inside it.this.socket
is equivalent to element.socket
at the appropriate iteration[UPDATE] after pointed out by Felix Kling, forEach() provides a scope for each element.
See bind for more details.
If it is not a scope issue, it could mean that the library you are using does not work as expected. Maybe, try to log element
inside the forEach() to check if the WebSocket objects are what you expect.
edit
Upvotes: 1