为了账号安全,请及时绑定邮箱和手机立即绑定

如何正确地打破承诺链?

如何正确地打破承诺链?

茅侃侃 2019-07-02 14:24:51
如何正确地打破承诺链?基于以下问题:然后是jQuery链接和级联,然后是而被接受的答案,我想打破承诺链在某一点,但还没有找到正确的方式。确实有倍数 员额 关于但我还是迷路了。以原始问题中的示例代码为例: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), Menus.getSides(cantinas));}).then(function(meals, 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});
查看完整描述

3 回答

?
蓝山帝景

TA贡献1843条经验 获得超7个赞

首先,我认为最好是说你是在“绕开”承诺链,而不是“打破”它。

正如您所说,在一些地方对“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。cantinas.length == 0路径需要多一个(如果多个旁路被编码,则每个旁路需要一个)。此外,此模式还需要可靠地重新检测特定错误条件,因此errMessages对象-有些人可能会找到贬低。


查看完整回答
反对 回复 2019-07-02
?
慕田峪7331174

TA贡献1828条经验 获得超13个赞

听起来像你支部不折断-你想继续和往常一样done..承诺的一个优点是,它们不仅是连锁的,而且可以是嵌套和非嵌套没有限制。在你的例子中,你可以把你想要“挣脱”的链条的一部分放在你的if-声明:

Menus.getCantinas().then(function(cantinas) {
    Menus.cantinas = cantinas;

    if (cantinas.length == 0)
        return Menus; // break!

    // 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;
    });}).done(function(Menus) {
    // with no cantinas, or with everything});


查看完整回答
反对 回复 2019-07-02
?
萧十郎

TA贡献1815条经验 获得超13个赞

对于使用内置浏览器承诺的人来说,他们需要寻找一种方法来停止承诺链,而不让所有消费者都知道拒绝案例,从而触发任何链接。thencatch或者扔东西Uncaught (in promise)错误,您可以使用以下方法:

var noopPromise = {
  then: () => noopPromise, 
  catch: () => noopPromise}function haltPromiseChain(promise) {
  promise.catch(noop)

  return noopPromise}// Use it thus:var p = Promise.reject("some error")p = haltPromiseChain(p)p.catch(e => console.log(e))
   // this never happens

从根本上说,nooppro而论是一个基本的存根承诺接口,它使用链接函数,但从不执行任何函数。这依赖于这样一个事实,即浏览器显然使用鸭子类型来确定某件事情是否是一种承诺,所以YMMV(我在Chrome 57.0.2987.98中测试了这一点),但如果这成为一个问题,您可能会创建一个实际的承诺实例,并对其当时和捕获方法进行中性处理。


查看完整回答
反对 回复 2019-07-02
  • 3 回答
  • 0 关注
  • 480 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信