在继续之前,我怎样才能确定一组延期被解决或被拒绝?

时间:2015-08-04 18:04:51

标签: jquery jquery-deferred

我遇到了一个问题,我需要进行三次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);

这有两个问题。一个是它感觉比它应该更难。

第二个更重要的问题是$。当所有问题都已解决时执行.done(),但是一旦被拒绝就会执行.fail()。我真正需要的是在所有承诺不再悬而未决之后执行的事情,无论它们是成功解决还是被拒绝。 $ .when似乎差不多,但并不完全是我想要的。在我检索(或无法检索)三个字符串中的每一个字符串之前,我不想显示该页面。我怎么能这样做?

1 个答案:

答案 0 :(得分:0)

answer you found并不是这个问题的完整答案。它让你只有一部分。

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

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

这三件事可以通过形成三个 for (var dex=3;dex<=6;dex++){ alert(dex); var depthBar =svgbin.selectAll("rect"+dex) .data(bindata) .enter() .append("rect") .attr("x", function(d) { return xScale(d[0]); }) .attr("y", function(d) { d.push(dex) return yupScale(accumDepth(d,3,dex)); }) .attr("width", function(d){ return binScale(d[1]); }) .attr("height", function(d) { return height-margin.bottom - yupScale(d[dex]); }) .style("opacity", 0.8) .attr("fill", barcolor[dex]) .attr("stroke","black") .on("mouseover", function(d,dex) { //Get this bar's x/y values, then augment for the tooltip var xPosition =parseFloat(d3.select(this).attr("x")) + xLable.rangeBand(); var yPosition = parseFloat(d3.select(this).attr("y")) + height*1.5; var start = d[0]; var end = d[0] + d[1]; var posvale = start + ".." + end; //Update the tooltip position and value d3.select("#tooltip") .style("left", xPosition + "px") .style("top", yPosition + "px") .select("#value") .text(dex); d3.select("#tooltip") .select("#title") .text("Depth:"); d3.select("#tooltip") .select("#posvalue") .text(posvale); //Show the tooltip d3.select("#tooltip").classed("hidden", false); }) .on("mouseout", function() { //Hide the tooltip d3.select("#tooltip").classed("hidden", true); }); } 链来实现,每个链都有一个错误处理程序,它返回一个用所需的默认字符串解析的jQuery promise:

$.ajax(...).then(...)

同样$.ajax(...).then(null, function() { return $.when('default'); }); 必须返回 promise (缓存的聚合承诺)。在涉及异步派生数据的情况下,唯一可靠的方法是返回一个promise(数据的抽象),而不是数据本身。

为了使代码更整洁,你可以做其他几件事:

  • 有条件地从.getStrings()致电.initialize(),以防它尚未被调用。
  • 汇总.getStrings()中的承诺并缓存生成的承诺,而不是单独缓存三个jqXHR承诺。
  • 清除.initialize(),转而直接致电.doThingWithStrings()。当.getStrings()返回的对象是一个promise时,有一个接受回调的中间方法没有优势,其.getStrings()方法本身会接受成功/错误回调。

此处.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()