javascript 在 Ajax 回调中访问 `this`,全部在一个对象中
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/19274673/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Accessing `this` in Ajax callback, all within an Object
提问by jmpp
I'm dealing with a problem about an Ajax callback inside of an Object. Please consider this code :
我正在处理有关对象内部 Ajax 回调的问题。请考虑以下代码:
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.
我收到一个错误Object success has no method loadResult
,这是有道理的,因为回调是匿名 jQuery 函数的一部分。
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.
我一直在尝试一个 var that = this; 在 Ajax 调用之前,但出于同样的原因,我不会工作。
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.
铅解决了。
回答by Explosion Pills
There are several ways to do this.
有几种方法可以做到这一点。
You can set the context
setting for the ajax options:
您可以设置context
ajax 选项的设置:
jQuery.ajax
context
setting
jQuery.ajax
context
环境
$.ajax({
context: this
Function.prototype.bind
Function.prototype.bind
.done(function (res) {
}.bind(this));
However, this is not as widely supported as...
然而,这并不像……那样得到广泛支持。
jQuery.proxy
jQuery.proxy
Created for this purpose.
为此目的而创建。
.done($.proxy(function (res) {
}, this);
Assigning this to another value
将此分配给另一个值
var self = this;
$.ajax({
/* snip */
.done(function (res) {
self.loadResults(res);
This is commonly done in JavaScript to give access to this
in lower scopes.
这通常在 JavaScript 中完成,以便this
在较低的范围内访问。
Arrow functions with lexical binding
带有词法绑定的箭头函数
$.ajax({
/* snip */
.then(res => this.loadResults(res));
回答by pala?н
回答by Alnitak
You can use the ES5 .bind
function to set this
correctly:
可以使用 ES5.bind
函数进行this
正确设置:
$.ajax(...).done(this.loadResults.bind(this));
(use the shim at the above link, or the jQuery $.proxy
equivalent on older browsers).
(使用上面链接中的 shim,或$.proxy
旧浏览器上的 jQuery等效项)。
Alternatively, add context: this
to the $.ajax
options:
或者,添加context: this
到$.ajax
选项:
$.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
.
请注意,在任何一种情况下,您都将覆盖 jQuery 中传递 ajax 选项对象的默认行为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.
ps链return
的结果也是一个很好的做法,$.ajax()
这样你的对象的用户可以将额外的回调(例如.fail
处理程序)链接到它。