Bug Tracker

Modify

Ticket #5853 (closed bug: duplicate)

Opened 3 years ago

Last modified 3 years ago

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:
Blocking: Blocked by:

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

comment:1 Changed 3 years ago by john

  • Status changed from new to closed
  • Resolution set to duplicate

Duplicate of #5838.

comment:2 Changed 3 years ago by borgar

  • Status changed from closed to reopened
  • Resolution duplicate deleted

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 3 years ago by borgar

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

comment:4 Changed 3 years ago by addyosmani

  • Keywords ajax callback context added
  • Status changed from reopened to closed
  • Resolution set to duplicate

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

comment:5 Changed 3 years ago by addyosmani

Duplicate of #5924.

Please follow the  bug reporting guidlines and use  jsFiddle when providing test cases and demonstrations instead of pasting the code in the ticket.

View

Add a comment

Modify Ticket

Action
as closed
Author


E-mail address and user name can be saved in the Preferences.

 
Note: See TracTickets for help on using tickets.