5

I'm a newbee about jQuery's workflow and I would like to setup a javascript class that uses an internal method to make an AJAX request. When the request returns with success, the jQuery AJAX callback should invoke a method owned by the class itself. That's the code:

function IXClock()
{
    this.m_intervalID = 0;

    this.startClock = function ()
    {
        this.m_intervalID = setInterval(this.tictac, 500);
    }

    this.stopClock = function ()
    {
        clearInterval(this.m_intervalID);
    }

    this.setClockTime = function(p_strTime)
    {
        $('#clock').html(p_strTime);
    }

    this.tictac = function ()
    {
        $.ajax
        ({
                type: 'POST',
                url: '/rap/rapClock.php',
                complete: function (data)
                {
                    this.setClockTime(data);
                }
        });
    }

}

The class represents a clock, with an internal method (tictac) that requests "what's the time" on the server side. After the server says the time, the jQuery's AJAX method should invoke the setClockTime method of the IXClock class. The invoke method will update the #clock div item in the html page.

The problem is that the method this.setClockTime() results unknown and the javascript return the "this.setClockTime is not a function" error.

The question is: is there a way to invoka a class method from the jQuery's AJAX callback ?

2
  • If you are calling it a class, why don't you use the prototype object to assign the methods to the class rather than attach them individually to each instantiated object? Commented Sep 14, 2010 at 10:49
  • Get the time once, format it to a date object, increment from there, it's kinda wasteful to use an ajax request in an interval. Commented Sep 14, 2010 at 10:55

5 Answers 5

12

I think that the problem is that the this in your callback function is different from the this referring to IXClock. Try:

var thisClass = this ;
this.tictac = function ()
{
    $.ajax
    ({
            type: 'POST',
            url: '/rap/rapClock.php',
            complete: function (data)
            {
                thisClass.setClockTime(data);
            }
    });
}

Test Case (added to site which already has jQuery loaded):

function uClass () {
    this.testFunction = function(input) {
        alert(input) ;
    }
    this.ajaxFunction = function() {
        var myClass = this ;
        $.ajax({
            type: 'POST',
            url: '/',
            complete: function(data) {
                alert(myClass.testFunction) ;
                myClass.testFunction(data) ;
                this.testFunction(data) ;
            }
        }) ;
    }
}

var k = new uClass() ;
k.ajaxFunction() ;
Sign up to request clarification or add additional context in comments.

9 Comments

Seems like the perfect solution, but I get the same error: thisClass.setClockTime is not a function
Hi, I have added a test case to my answer which should demonstrate the solution and the error you experienced. Does this work for you? If not, can you provide more detail of how you are using IXClock, and what version of jQuery you are running?
It's exactly like yours. Seems strange, here is mine: iakko.net/jquery-ajax
Ah - because the tictac() function is being called by window.setInterval, the this that you are setting to myClass is the window object. You will need to move the line var myClass = this ; into the IXClock() definition, just above the line this.tictac = function(). Sorry.
Well, that's the same thing again! If I put myClass outside tictac, how should I reference to myClass from inside the AJAX callback? Take a look to the same url: iakko.net/jquery-ajax . The same error again! Am I missing something ?
|
2

It happens bacause your callback function leave in global context.

You can choose 2 ways

  1. Use .bind function to bind context to callback function http://www.robertsosinski.com/2009/04/28/binding-scope-in-javascript/

  2. jQuery's AJAX supports transfer some data to callback function. You can write smth like this:

:

this.tictac = function () { $.ajax ({ type: 'POST', context:this, url: '/rap/rapClock.php', complete: function (data) { this.setClockTime(data); } }); }

}

Comments

0

this does not refer to IXClock in your ajax callback. this allways points to the current scope (have a look at this document). You need to do something like this:

this.prototype.tictac = function ()
{
    var self = this;
    $.ajax
    ({
        type: 'POST',
        url: '/rap/rapClock.php',
        complete: function (data)
        {
            self.setClockTime(data);
        }
    });
}

You can also use jQuery's .proxy()-function for this purpose:

this.prototype.tictac = function ()
{
    $.ajax
    ({
        type: 'POST',
        url: '/rap/rapClock.php',
        complete: $.proxy(function (data) {
            this.setClockTime(data);
        }, this)
    });
}

1 Comment

Why has this been downvoted again? If you do not like my answer, tell me why! I do not see any errors here.
0

The this in the result handler is not what you expect it is. (It is not the IXClock instance)

function IXClock()
{
    this.m_intervalID = 0;
}

IXClock.prototype = {

    startClock: function ()
    {
        this.m_intervalID = setInterval(this.tictac, 500);
    },

    stopClock: function ()
    {
        clearInterval(this.m_intervalID);
    },

    setClockTime: function(p_strTime)
    {
        $('#clock').html(p_strTime);
    },

    tictac: function ()
    {
        var that = this;
        $.ajax({
            type: 'POST',
            url: '/rap/rapClock.php',
            success: function (data) { // You want success here, not complete, IMO
                that.setClockTime(data);
            }
        });
    }

}

If you ask me, that ajax call is doing evil. It does not seem to send any data, nor modify any state on the server, but is expecting/getting/using data from the php, yet is using the POST method. Should've been

$.get('/rap/rapClock.php', function (data) {
    that.setClockTime(data);
});

Comments

0

One simple solution is, to keep your callback function as self = this. This will support inheritance also.

class Record{
  get_data(){
    self = this;
    $.ajax({
        type : "GET",
        url : "/get_url",
        dataType : "json",
        contentType: "application/json; charset=utf-8",
        data : {},
        success : function(data){
          console.log(data);
          self.load_table(data);
        },
      });
  }

  static load_table(data){
    console.log(data);
  }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.