admin管理员组

文章数量:1400628

I am recently working on small chat module , which require continuously checking the server for new message.

I am sending a ajax request to a server , and the server hold's the connection until new message is found(long polling).

Code :

var chatController = function(){
 
//other variable declaration

/**
*  Ajax call to monitor the new message , on plete of ajax call sending other call
*/

this.checkNewMessage = function(){
  console.log(this); // placed this for debugging purpose
       $.ajax({
         url : SITEURL.CHECK_MESSAGE,
         data : this.currrentUserDetails,
         dataType : 'json' ,
         cache    : false,
         success  :(function(obj){
            //temp = obj;
            return obj.parseNewMessageResponse;
         })(this),
         plete: (function(obj){
            //temp = obj;
            return obj.checkNewMessage;
         })(this),  
       });
       
     
};

  // other function and variable

});

When i tried to call

var mainController = new chatController();
mainController.checkNewMessage();

Problem

What i thought was that i would be able to send continuous single request to server, but to my surprise I only could send 2 ajax request one after the other.

My Debugging

When i tried to debug , i traced out that for the first call this object being passed points to the chatController

         plete: (function(obj){
            return obj.checkNewMessage;
         })(this),     // this here point to chatController object
         
         

For the second time this object being passed points to the ajax object

         plete: (function(obj){
            return obj.checkNewMessage;
         })(this),     // this here point to ajax object

I am using JavaScript closure to pass the chatController object to plete parameter of jquery

So what i want is way to pass parameter to jQuery plete function so that it's point to my original reference

I am recently working on small chat module , which require continuously checking the server for new message.

I am sending a ajax request to a server , and the server hold's the connection until new message is found(long polling).

Code :

var chatController = function(){
 
//other variable declaration

/**
*  Ajax call to monitor the new message , on plete of ajax call sending other call
*/

this.checkNewMessage = function(){
  console.log(this); // placed this for debugging purpose
       $.ajax({
         url : SITEURL.CHECK_MESSAGE,
         data : this.currrentUserDetails,
         dataType : 'json' ,
         cache    : false,
         success  :(function(obj){
            //temp = obj;
            return obj.parseNewMessageResponse;
         })(this),
         plete: (function(obj){
            //temp = obj;
            return obj.checkNewMessage;
         })(this),  
       });
       
     
};

  // other function and variable

});

When i tried to call

var mainController = new chatController();
mainController.checkNewMessage();

Problem

What i thought was that i would be able to send continuous single request to server, but to my surprise I only could send 2 ajax request one after the other.

My Debugging

When i tried to debug , i traced out that for the first call this object being passed points to the chatController

         plete: (function(obj){
            return obj.checkNewMessage;
         })(this),     // this here point to chatController object
         
         

For the second time this object being passed points to the ajax object

         plete: (function(obj){
            return obj.checkNewMessage;
         })(this),     // this here point to ajax object

I am using JavaScript closure to pass the chatController object to plete parameter of jquery

So what i want is way to pass parameter to jQuery plete function so that it's point to my original reference

Share Improve this question edited Jun 20, 2020 at 9:12 CommunityBot 11 silver badge asked Sep 3, 2014 at 6:04 sanjeevsanjeev 4,6512 gold badges21 silver badges28 bronze badges 6
  • stackoverflow./questions/5316697/… – Parfait Commented Sep 3, 2014 at 6:07
  • you can define "this" into variable and then use it. like var $thisChatController = this; – Sohil Desai Commented Sep 3, 2014 at 6:08
  • @SohilDesai can you show me some example, thanks – sanjeev Commented Sep 3, 2014 at 6:15
  • @Parfait i want to pass a same object function in the callback – sanjeev Commented Sep 3, 2014 at 6:16
  • you can implement it with Signal R , this is a sample of chat application in codeproject./Articles/524066/… if you are using some other language you can integrate it with that too...... – ankur Commented Sep 3, 2014 at 6:25
 |  Show 1 more ment

3 Answers 3

Reset to default 6

There are various posible cross-browser solutions

You can use $.proxy:

In my opinion, the best practice.

$.ajax({
    //...
    success: $.proxy(function(json) {
         // `this` refers to the second argument of `$.proxy`
    }, this)
});

You can set the context option:

$.ajax({
    //...
    context: this,
    success: function(json) {
         // `this` refers to the value of `context`
    }
});

Or use a closure:

var self = this;
$.ajax({
    //...
    success: function(json) {
         // `this` refers to ajax request, use self instead
         $(self).dosomething();
    }
});

There are at least four different ways to solve the issue of not calling your method with the right context from your success and plete handlers.

  1. Use the context argument for $.ajax() so that this in your success handler will be what you want it to be so you can then call your method.

  2. Use .bind() to create a new function stub that calls your method with the right context.

  3. Save the value of this into a local variable so you can reference that variable when you need it in a stub function.

  4. Use jQuery's cross browser version of .bind() which is called $.proxy().

I will offer you some examples of each.

First, the context option for $.ajax():

this.checkNewMessage = function(){
  console.log(this); // placed this for debugging purpose
       $.ajax({
         context: this,
         url : SITEURL.CHECK_MESSAGE,
         data : this.currrentUserDetails,
         dataType : 'json' ,
         cache    : false,
         success  : function(data) {
             this.parseNewMessageResponse(data);
         },
         plete : function(data) {
             this.checkNewMessage();
         }
       });
};

Then, using .bind().

this.checkNewMessage = function(){
  console.log(this); // placed this for debugging purpose
       $.ajax({
         url : SITEURL.CHECK_MESSAGE,
         data : this.currrentUserDetails,
         dataType : 'json' ,
         cache    : false,
         success  : this.parseNewMessageResponse.bind(this),
         plete : this.checkNewMessage.bind(this)
       });
};

Then, using a saved copy of this:

this.checkNewMessage = function(){
     var self = this;
     console.log(this); // placed this for debugging purpose
       $.ajax({
         url : SITEURL.CHECK_MESSAGE,
         data : this.currrentUserDetails,
         dataType : 'json' ,
         cache    : false,
         success  : function(data) {
             self.parseNewMessageResponse(data);
         },
         plete : function(data) {
             self.checkNewMessage();
         }
       });
};

And finally with jQuery's `.proxy():

this.checkNewMessage = function(){
  console.log(this); // placed this for debugging purpose
       $.ajax({
         url : SITEURL.CHECK_MESSAGE,
         data : this.currrentUserDetails,
         dataType : 'json' ,
         cache    : false,
         success  : $.proxy(this.parseNewMessageResponse, this),
         plete : $.proxy(this.checkNewMessage, this)
       });
};

If you don't need IE8 support or you're fine with installing a polyfill for .bind(), then the .bind() option is my favorite because it just seems the cleanest.

The easiest way to solve this is to define a reference to your original this so you can access it from another context. Check this simple example:

(function(){
  var _self = this;

  function changeColor($element, color){
    $element.css("background-color", color)
  }

  $(".recolor-btn").click(function(){
    var self = this;
    $.ajax({
      url: "/Color/GetRandom",
      success: function(color){
        _self.changeColor($(self), color);
      }
    });
  });

})();

本文标签: javascriptpassing object to callback function in jqueryStack Overflow