0

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?)

  • At the start of your function do this: var me = this; and then use me instead of this. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this Edit: Oh you're even caching it in your other function. Do that for the whole thing. – WakeskaterX Apr 14 '15 at 12:36
  • Welcome to [so]. It appears your question is answered here: [Pass correct "this" context to setTimeout callback?](http://stackoverflow.com/questions/2130241/pass-correct-this-context-to-settimeout-callback) Please let me know if that doesn't answer your question. – Qantas 94 Heavy Apr 14 '15 at 12:37
  • @WakeskaterX He already has a reference to `this`, he just isn't using it. – Ben Fortune Apr 14 '15 at 12:37
  • Hah, yeah just noticed. He should pull that into the overall scope of the client though so he has a reference for all his functions. EDIT: Nevermind, it's not even a function, my reading skills this morning are slow. I see what he's doing now, and yes you're right. – WakeskaterX Apr 14 '15 at 12:38
  • 1
    `setTimeout(clientObj.connect.bind(clientObj)...` – Ben Fortune Apr 14 '15 at 12:39

1 Answers1

3

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.

robertklep
  • 198,204
  • 35
  • 394
  • 381
  • It actualy worked well - this.socket.on('data', this.dataParser) when it called from right context. Problem was only in timeout. I thought that it's wrong something at context binding, now it's clear to me. thx=) – user2700517 Apr 14 '15 at 13:13