Bug Tracker

Opened 10 years ago

Closed 9 years ago

Last modified 9 years ago

#5853 closed bug (duplicate)

Ajax callback context is not original object.

Reported by: borgar Owned by:
Priority: major Milestone: 1.4.1
Component: ajax Version: 1.4
Keywords: ajax callback context Cc:
Blocked by: Blocking:

Description

Callbacks pass a different object as a context than the one originally assigned, if the original object is a literal object.

var ctx = {};
$.ajax({
  context: ctx,
  success: function () {
    console.log( this === ctx );  // false
  }
});

My understanding is that this happens because $.extend is now cloning literal objects rather than copying the reference. Settings are passed through $.extend and the context is read from them, rather than original settings. Thus all literal objects passed in as a context will be replaced by a fresh identical objects. Preventing any assignments to them.

The fix should be simple:

ajax: function( origSettings ) {
	var s = jQuery.extend(true, {}, jQuery.ajaxSettings, origSettings);
	var jsonp, status, data,
		callbackContext = s.context || s,
	// ...

This should be something like:

ajax: function( origSettings ) {
	var s = jQuery.extend(true, {}, jQuery.ajaxSettings, origSettings);
	var jsonp, status, data,
		callbackContext = (origSettings && origSettings.context) || s,
	// ...

Change History (5)

comment:1 Changed 10 years ago by john

Resolution: duplicate
Status: newclosed

Duplicate of #5838.

comment:2 Changed 10 years ago by borgar

Resolution: duplicate
Status: closedreopened

This is absolutely not a duplicate of #5838.

This is a separate issue that happens when a literal object or array IS SET as the context property: The callback context is a fresh object that looks the same, feels the same, but is not the same. For all other object types the same object is passed through:

var ctx = function(){};
$.ajax({
  context: ctx,
  success: function () {
    console.log( this === ctx );  // true
  }
});

See additional (potential) problems in forum post: http://forum.jquery.com/topic/ajax-contexts

Here is a slightly more complex, but closer to real-world scenario which illustrates how this is failing for me:

(function(){

  var private = {
    cache: null,
    loaddata: function () {
      if ( !this.cache ) {
        console.log( 'no cache present' );
        $.ajax({
          async: false,  // ignore this, it's for the demo to work
          context: this,
          success: function ( r ) {
            this.cache = r;   // where does r go?
          }
        });
      }
    }
  };

  $.loader = function () { private.loaddata(); };

})();

$.loader();
$.loader();  // keeps loading because cache is empty
$.loader();  // ... and so on

Not only is the private object inaccessible within the success callback but effort is also wasted on cloning the object (and it's empty cache member) every call to $.ajax.

I guess the programmer can still use closures, we've been doing fine with them until now. My problem with this is that it SEEMS to work, but doesn't.

comment:3 Changed 10 years ago by borgar

This is a duplicate of #5924, or rather it of this. Fixed in 1.4.1.

comment:4 Changed 9 years ago by addyosmani

Keywords: ajax callback context added
Resolution: duplicate
Status: reopenedclosed

This is a duplicate of #5924 which had a fix made for it in 1.4.1. Closing.

comment:5 Changed 9 years ago by addyosmani

Duplicate of #5924.

Note: See TracTickets for help on using tickets.