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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-27 14:57:49  来源:igfitidea点击:

Accessing `this` in Ajax callback, all within an Object

javascriptjqueryajaxobject

提问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 contextsetting for the ajax options:

您可以设置contextajax 选项的设置:

jQuery.ajaxcontextsetting

jQuery.ajaxcontext环境

$.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 thisin lower scopes.

这通常在 JavaScript 中完成,以便this在较低的范围内访问。

Arrow functions with lexical binding

带有词法绑定的箭头函数

$.ajax({
/* snip */
.then(res => this.loadResults(res));

回答by pala?н

You can use the $.ajax()contextobject here like:

您可以在此处使用$.ajax()context对象,例如:

$.ajax({
    url : 'http://api.deezer.com/search/track/',
    context: this,
    ...
}).done(function (res) {
    this.loadResults( res );
});

回答by Alnitak

You can use the ES5 .bindfunction to set thiscorrectly:

可以使用 ES5.bind函数进行this正确设置:

$.ajax(...).done(this.loadResults.bind(this));

(use the shim at the above link, or the jQuery $.proxyequivalent on older browsers).

(使用上面链接中的 shim,或$.proxy旧浏览器上的 jQuery等效项)。

Alternatively, add context: thisto the $.ajaxoptions:

或者,添加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 returnthe result of the $.ajax()chain so that the user of your object can chain additional callbacks (e.g. a .failhandler) to it.

ps链return的结果也是一个很好的做法,$.ajax()这样你的对象的用户可以将额外的回调(例如.fail处理程序)链接到它。