Kaspi
Kaspi

Reputation: 3678

Javascript - "this" is empty

I am trying to write server side for my web application using Node.js. The following code is extracted to simulate the situation. Problem is that the application crashes when trying to access this.actions.length in the actionExecuted "method". The property this.actions is undefined there (this == {} within the scope) even it was defined in the "constructor" (the Request function itself). How to make the actions property accessible from other "methods" as well?

var occ = {
    exampleAction: function(args, cl, cb)
    {
        // ...

        cb('exampleAction', ['some', 'results']);
    },

    respond: function()
    {
        console.log('Successfully handled actions.');
    }
};

Request = function(cl, acts)
{
    this.client = cl;
    this.actions = [];
    this.responses = [];

    // distribute actions
    for (var i in acts)
    {
        if (acts[i][1].error == undefined)
        {
            this.actions.push(acts[i]);
            occ[acts[i][0]](acts[i][1], this.client, this.actionExecuted);
        }
        else
            // such an action already containing error is already handled,
            // so let's pass it directly to the responses
            this.responses.push(acts[i]);
    }
}

Request.prototype.checkExecutionStatus = function()
{
    // if all actions are handled, send data to the client
    if (this.actions == [])
        occ.respond(client, data, stat, this);
};

Request.prototype.actionExecuted = function(action, results)
{
    // remove action from this.actions
    for (var i = 0; i < this.actions.length; ++i)
        if (this.actions[i][0] == action)
            this.actions.splice(i, 1);

    // and move it to responses
    this.responses.push([action, results]);
    this.checkExecutionStatus();
};

occ.Request = Request;

new occ.Request({}, [['exampleAction', []]]);

Upvotes: 1

Views: 1164

Answers (1)

Ben Lee
Ben Lee

Reputation: 53349

The problem is the way you are defining your callback. It's called later so it loses context. You have to either create a closure or properly bind the this. To create a closure:

var self = this;
occ[acts[i][0]](acts[i][1], this.client, function() { self.actionExecuted(); });

To bind to this:

occ[acts[i][0]](acts[i][1], this.client, this.actionExecuted.bind(this));

Either one should work.

Upvotes: 2

Related Questions