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 comment:1
resolution: | → duplicate |
---|---|
status: | new → closed |
Changed January 23, 2010 01:10PM UTC by comment:2
resolution: | duplicate |
---|---|
status: | closed → reopened |
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 comment:3
This is a duplicate of #5924, or rather it of this. Fixed in 1.4.1.
Duplicate of #5838.