'Accessing `this` in Ajax callback, all within an Object
I'm dealing with a problem about an Ajax callback inside of an Object. Please consider this code :
Search.prototype =
{
ask : function( query )
{
// Display loader
$('.loader').show();
$.ajax({
dataType : 'jsonp',
type : 'GET',
url : 'http://api.deezer.com/search/track/',
data : {
output : 'jsonp',
q : query
}
}).done(function(res) {
this.loadResults( res );
// [Error] Object success has no method 'loadResult'
});
},
loadResults : function (res)
{
// Hide loader
$('.loader').hide();
console.log( res );
// doing some stuff
// ...
}
}
var search = new Search();
search.ask( 'eminem' );
I get an error Object success has no method loadResult , which makes sense as the callback is part of an anonymous jQuery function.
But how to get my initial object instance ?
I've been trying with a var that = this; before the Ajax call, but I't won't works for the same reasons.
I don't know if it's possible to do this or if the problem comes from my code global organization. Feel free to advise me about the best practices :)
Thanks by advance.
[Update (solved)]
I obfuscated some things in my code which I though it was unnecessary to post here, but I finally found out the problem a little bit earlier in my code. Sorry about that.
Here's my full code, which is now working :
define(['jquery'], function($) {
var Search = function()
{
this._keyDownTimer = 0;
this._searchDelay = 1000; // ms
};
Search.prototype =
{
// The init function that I though it was unnecessary to post here. Sorry :/
init : function()
{
$('#q').on('keydown', (function(evt) {
clearTimeout( this._keyDownTimer );
this._keyDownTimer = setTimeout( (function() {
this.ask( $('#q').val() );
}).bind( this ), this._searchDelay); /* <-- Here's the solution.
I forgot to bind `this`
to the timeout callback function,
so the `this` under all of my code
was referring to the anonymous function
of this callback. */
}).bind( this ));
},
ask : function( query )
{
// Display loader
$('.loader').show();
console.log(this); // Now `this` refers to my object :)
var req = $.ajax({
dataType : 'jsonp',
type : 'GET',
url : 'http://api.deezer.com/search/track/',
context : this,
data : {
output : 'jsonp',
q : query
}
});
req.done(function(res) {
this.loadResults(res);
});
},
loadResults : function (res)
{
// Hide loader
$('.loader').hide();
// doing some stuff
// ...
}
};
return new Search;
});
Thanks for your replies, it really helped.
Pb solved.
Solution 1:[1]
You can use the $.ajax() context object here like:
$.ajax({
url : 'http://api.deezer.com/search/track/',
context: this,
...
}).done(function (res) {
this.loadResults( res );
});
Solution 2:[2]
You can use the ES5 .bind function to set this correctly:
$.ajax(...).done(this.loadResults.bind(this));
(use the shim at the above link, or the jQuery $.proxy equivalent on older browsers).
Alternatively, add context: this to the $.ajax options:
$.ajax({
...,
context: this
}).done(this.loadResults);
Note that in either case you will override jQuery's default behaviour of passing the ajax option object in this.
p.s. it's also good practise to return the result of the $.ajax() chain so that the user of your object can chain additional callbacks (e.g. a .fail handler) to it.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | palaѕн |
| Solution 2 |
