根据这个问题:
jQuery chaining and cascading then’s and when’s和接受的答案。
我想在某一时刻打破承诺链,但还没有找到正确的方法。有multiple posts about这个,但我还是迷失了。
Menus.getCantinas().then(function(cantinas){ // `then` is how we chain promises Menus.cantinas = cantinas; // if we need to aggregate more than one promise,we `$.when` return $.when(Menus.getMeals(cantinas),Menus.getSides(cantinas)); }).then(function(meals,sides){ // in jQuery `then` can take multiple arguments Menus.sides = sides; // we can fill closure arguments here Menus.meals = meals; return Menus.getAdditives(meals,sides); // again we chain }).then(function(additives){ Menus.additives = additives; return Menus; // we can also return non promises and chain on them if we want }).done(function(){ // done terminates a chain generally. // edit HTML here });
如果cantinas.length == 0,我将如何破解链?我不想要吃饭,既不是添加剂,坦白说,我想打电话给某种“空结果”回调。我尝试了以下这是非常丑陋(但工作…)。教我正确的方法。这仍然是一个有效的结果,所以不是一个“失败”本身,只是空的结果我会说。
var emptyResult = false; Menus.getCantinas().then(function(cantinas){ Menus.cantinas = cantinas; if (cantinas.length == 0) { emptyResult = true; return "emptyResult"; //unuglify me } return $.when(Menus.getMeals(cantinas),sides){ if (meals == "emptyResult") return meals; //look at my ugliness... Menus.sides = sides; Menus.meals = meals; return Menus.getAdditives(meals,sides); }).then(function(additives){ if (additives == "emptyResult") return additives; Menus.additives = additives; return Menus; }).done(function(){ if (emptyResult) //do empty result stuff else // normal stuff });
解决方法
首先,我认为更好地说,你正在寻求“绕过”承诺链的一部分,而不是“打破”它。
正如你所说,在几个地方测试“emptyResult”是相当难看的。幸运的是,一个更优雅的机制是可以遵守同样的一般原则,不执行一些承诺链。
一种替代机制是使用承诺拒绝来控制流量,然后重新检测链中稍后的特定错误条件,并将其放回成功路径。
Menus.getCantinas().then(function(cantinas) { Menus.cantinas = cantinas; if(cantinas.length == 0) { return $.Deferred().reject(errMessages.noCantinas); } else { return $.when(Menus.getMeals(cantinas),Menus.getSides(cantinas)); } }).then(function(meals,sides) { Menus.sides = sides; Menus.meals = meals; return Menus.getAdditives(meals,sides); }).then(function(additives) { Menus.additives = additives; return Menus; }).then(null,function(err) { //This "catch" exists solely to detect the noCantinas condition //and put the chain back on the success path. //Any genuine error will be propagated as such. //Note: you will probably want a bit of safety here as err may not be passed and may not be a string. return (err == errMessages.noCantinas) ? $.when(Menus) : err; }).done(function(Menus) { // with no cantinas,or with everything }); var errMessages = { 'noCantinas': 'no cantinas' };
在另一方面,我发现缺乏嵌套使得更好的可读性成为自然的成功之路。此外,至少对于我来说,如果需要,这种模式将需要极少的精神杂耍来适应进一步的绕行。
在这方面,这种模式比Bergi的效率稍差一些。而主路径与Bergi的承诺数量相同,所以cantinas.length == 0路径需要一个(如果多个旁路被编码,则需要一个旁路)。此外,这种模式需要可靠地重新检测特定的错误条件 – 因此,errMessages对象 – 哪些可能会发现减损。