Tuesday, 5 September 2017

javascript - Strange with nodejs/js in using "this" after callback in setTimeout





It's very strange. I have code:



var client = {

init: function () {
this.connect();

return this;
},

connect: function () {
var clientObj = this;

this.socket = net.connect({
port: config.port,
host: config.host
}, function () {

log_ts('Connected to serv');
});

this.socket.on('data', this.dataParser);

this.socket.on('end', function () {
logerr_ts('Disconnected from serv');
logerr_ts('Trying to reconnect after '+config.reconnectTimeout + 'ms');
setTimeout(clientObj.connect, config.reconnectTimeout);
});

},

dataParser: function (data) {
//analyzing data from me6d server
}
};


Now when it became disconected from serv, it's trying to reconnect and i'm getting this error:




2015-04-12 15:22:12  Trying to reconnect after 500ms
events.js:142
throw TypeError('listener must be a function');
^
TypeError: listener must be a function
at TypeError (native)
at Socket.addListener (events.js:142:11)
at Socket.Readable.on (_stream_readable.js:671:33)
at me6dClient.connect [as _onTimeout] (/var/www/nodejs/client/index.js:212:15)
at Timer.listOnTimeout (timers.js:110:15)



How it can be? this.dataParser is a function. may be it's somethink became bad when timeout is fired, it changes context for this ? But how?)


Answer



The problem is that using clientObj.connect as a reference will lose the context it's bound to.



You can rebind it like so:



setTimeout(clientObj.connect.bind(clientObj), ...);



This basically means "when the timeout is reached, call clientObj.connect using clientObj as this".



FWIW, the same is happening here:



this.socket.on('data', this.dataParser)


The dataParser method will also be called without the right context. That issue (if it actually is an issue) can be solved in a similar fashion.


No comments:

Post a Comment

casting - Why wasn't Tobey Maguire in The Amazing Spider-Man? - Movies & TV

In the Spider-Man franchise, Tobey Maguire is an outstanding performer as a Spider-Man and also reprised his role in the sequels Spider-Man...