Skip to main content

Bug Tracker

Side navigation

#5853 closed bug (duplicate)

Opened January 18, 2010 03:23PM UTC

Closed October 20, 2010 03:28AM UTC

Last modified October 20, 2010 03:28AM UTC

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,
	// ...
Attachments (0)
Change History (5)

Changed January 22, 2010 09:43PM UTC by john comment:1

resolution: → duplicate
status: newclosed

Duplicate of #5838.

Changed January 23, 2010 01:10PM UTC by borgar comment:2

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.

Changed January 26, 2010 12:40PM UTC by borgar comment:3

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

Changed October 20, 2010 03:28AM UTC by addyosmani comment:4

keywords: → ajax callback context
resolution: → duplicate
status: reopenedclosed

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

Changed October 20, 2010 03:28AM UTC by addyosmani comment:5

Duplicate of #5924.