我遇到了一个问题,我需要进行三次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似乎差不多,但并不完全是我想要的。在我检索(或无法检索)三个字符串中的每一个字符串之前,我不想显示该页面。我怎么能这样做?
答案 0 :(得分:0)
answer you found并不是这个问题的完整答案。它让你只有一部分。
缺少的最重要的是正确注入默认值,这是这个问题的核心。你需要知道如何:
这三件事可以通过形成三个 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()