jQuery延迟then()在解决之前调用

时间:2014-08-26 18:15:16

标签: jquery ajax jquery-deferred

我是jQuery的新手Deferred并且不明白为什么在成功函数完成之前调用它。我有两个同时的ajax请求,并希望触发一个UI单选按钮单击以迭代从其中一个ajax调用返回的一些数据,这需要20秒才能响应。但是,当在then()内触发单选按钮单击时,要迭代的数据为空。如果我单击另一个单选按钮来过滤数据,然后单击触发的单选按钮,则数据不为空,因为已经有足够的时间来成功加载对象。

对象在第一次(20秒)ajax调用成功加载,并且当这两个调用都被解析时,在then()中触发单击。如果成功完成,为什么然后()会触发点击?

    firstAjaxFunc: function(args){          
        return $.ajax({
            type: "POST",               
            url: REQUEST_URL + "/first-func",
            contentType: "application/json",
            data: $.toJSON({
                propOne: propOne,
                propTwo: propTwo
            }),
            dataType: "json class.models",
            context: args.context,
            success: args.success,
            error: showResponseError
        });
    },

    secondAjaxFunc: function(args){
        return $.ajax({
            type: "POST",               
            url: REQUEST_URL + "/second-func",
            contentType: "application/json",
            data: $.toJSON({
                propOne: propOne,
                propTwo: propTwo
            }),
            dataType: "json class.models",
            context: args.context,
            success: args.success,
            error: showResponseError
        });
    },

        $('#load-data').append('<p class="spinner" align="center"><img src="../images/loading_small.gif"/></p>');
        this.firstAjaxFunc({
            params: {
                propOne: propOne,
                propTwo: propTwo
            },
            success: function(data){
                this.options.stuff = data;
            },
            context: this
        });
        this.secondAjaxFunc({
            params: {
                propOne: propOne,
                propTwo: propTwo
            },
            success: function(data){
                this.options.moreStuff = data;
            },
            context: this
        });
        $.when(firstAjaxFunc, secondAjaxFunc).then(this.find(".filter-all").click());

    ".filter-all click": function(radio, event){ 
            this.showAllData();
    },

    showAllData: function(){
        for(var i = 0; i < this.options.stuff.length; i++){ // this.options.stuff is null
            $.merge(stuffArr, this.options.stuff[i].getMyStuff());
        }
    },

1 个答案:

答案 0 :(得分:4)

我看到两个主要问题。

$.when()接受promises作为参数,而不是回调函数。因此,您需要实际调用传递给它的函数,如下所示:

 $.when(this.firstAjaxFunc(...), this.secondAjaxFunc(...)).then(...);

AND,.then()处理程序必须是回调函数,因此您必须将.then()处理程序转换为稍后可以调用的回调函数。正如您现在所做的那样,它会立即执行,并将结果传递给.then(),这解释了为什么.click()会立即执行。


此外,最好不要将jQuery成功处理程序与promise处理程序混合使用。选择其中一个并始终如一地使用它们。在这种情况下,由于你需要一些promise函数,你应该只使用promises,因为promise规则中的调用顺序和promise处理程序序列是严格描述的,因此调用顺序不会有歧义。


您只是展示了一些代码,因此很难获得完整的上下文,但我认为您需要这样的内容:

    var p1 = this.firstAjaxFunc({
        params: {
            propOne: propOne,
            propTwo: propTwo
        },
        success: function(data){
            this.options.stuff = data;
        },
        context: this
    });
    var p2 = this.secondAjaxFunc({
        params: {
            propOne: propOne,
            propTwo: propTwo
        },
        success: function(data){
            this.options.moreStuff = data;
        },
        context: this
    });
    $.when(p1, p2).then(function() {
        this.find(".filter-all").click();
    }, showResponseError);

或者,将所有内容转换为承诺:

    var self = this;
    var p1 = this.firstAjaxFunc({
        params: {
            propOne: propOne,
            propTwo: propTwo
        }
    });
    var p2 = this.secondAjaxFunc({
        params: {
            propOne: propOne,
            propTwo: propTwo
        }
    });
    $.when(p1, p2).then(function(data1, data2) {
        // process the results
        self.options.stuff = data1[0];
        self.options.moreStuff = data2[0];

        // carry out action now that both are done
        this.find(".filter-all").click();
    }, showResponseError);