【问题标题】:How can I be sure that a group of deferreds are all resolved or rejected before continuing?在继续之前,我如何确定一组延期的都已解决或被拒绝?
【发布时间】:2015-08-05 10:56:52
【问题描述】:

我遇到了一个问题,我需要进行三个 Ajax 调用来检索一些字符串。如果其中任何一个失败,我需要使用默认字符串。我希望我的页面等到所有字符串都已解决(或拒绝)后再继续。

到目前为止,我所拥有的看起来像这样:

var myObj = {
    initialize: function(){
        // Start fetching this stuff right away
        var that = this;
        this.promise1 = $.ajax(url: 'url1').then(function(result){
            that.string1 = result
        ).fail(function(){
            that.string1 = 'string1Default';
        });
        this.promise2 = $.ajax(url: 'url2').then(function(result){
            that.string2 = result
        ).fail(function(){
            that.string2 = 'string2Default';
        });
        this.promise3 = $.ajax(url: 'url3').then(function(result){
            that.string3 = result
        ).fail(function(){
            that.string3 = 'string3Default';
        });
    }

    getStrings: function(){
        return {
            string1: this.string1, 
            string2: this.string2, 
            string3: this.string3
        };
    }

    doThingWithStrings: function(callback){
        var that = this;
        return $.when(this.promise1, this.promise2, this.promise3)
            .always(function(){callback(that.getStrings())})
    }
}

myObj.initialize(); // start fetching
// ... do some other stuff
myObj.doThingWithStrings(loadThePageWithStrings);

这有两个问题。一是感觉比应该的要难。

第二个更重要的问题是 $.when 在所有问题都解决后执行 .done() ,但在任何问题都被拒绝时执行 .fail() 。我真正需要的是在所有承诺不再待处理之后执行的东西,无论它们是成功解决还是被拒绝。 $.when 似乎几乎,但不完全是我想要的。在我检索(或检索失败)三个字符串中的每一个之前,我不想显示该页面。我该怎么做?

【问题讨论】:

  • 经过更多研究(我保证,我在写这篇文章之前看过!)我想这可能是this的副本

标签: jquery jquery-deferred


【解决方案1】:

answer you found 不是这个问题的完整答案。它只是让你到达那里的一部分。

缺少的最重要的事情是正确注入默认值,这是这个问题的核心。你需要知道如何:

  • 捕获 ajax 错误,
  • 注入默认值,
  • 将失败转化为成功。

这三件事可以通过形成三个$.ajax(...).then(...) 链来非常简单地实现,每个链都有一个错误处理程序,该处理程序返回一个使用所需默认字符串解析的 jQuery 承诺:

$.ajax(...).then(null, function() {
    return $.when('default');
});

同样.getStrings() 必须返回一个promise(缓存的聚合promise)。对于异步派生的数据,唯一可靠的方法是返回一个 promise(数据的抽象),而不是数据本身。

为了让代码更整洁,你可以做一些其他的事情:

  • 有条件地从.getStrings() 调用.initialize(),以防它尚未被调用。
  • 聚合.initialize() 中的promise 并缓存生成的promise,而不是单独缓存三个jqXHR promise。
  • 清除.doThingWithStrings() 以支持直接调用.getStrings()。当.getStrings() 返回的对象是一个promise 时,拥有一个接受回调的中间方法没有任何优势,其.then() 方法本身将接受成功/错误回调。

这里是myObj

var myObj = {
    initialize: function() {
        var promise1 = $.ajax({url: 'url1'}).then(null, function() {
            return $.when('string1Default');//inject default on ajax failure
        });
        var promise2 = $.ajax({url: 'url2'}).then(null, function() {
            return $.when('string2Default');//inject default on ajax failure
        });
        var promise3 = $.ajax({url: 'url3'}).then(null, function() {
            return $.when('string3Default');//inject default on ajax failure
        });
        this.promise = $.when(promise1, promise2, promise3).then(function (str1, str2, str3) {
            return {
                'string1': str1, 
                'string2': str2, 
                'string3': str3
            };
        }); 
    },
    getStrings: function() {
        if(!this.promise) {
            this.initialize();//safety, in case initialize() has not been called
        }
        return this.promise;
    }
}

这里是如何拨打myObj.getStrings()

myObj.getStrings().then(function(stringsObject) {
    // do stuff with stringsObject here.
    console.dir(stringsObject);
});

【讨论】:

    猜你喜欢
    • 2012-09-05
    • 1970-01-01
    • 2011-08-15
    • 1970-01-01
    • 2015-09-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多