承诺中的两个递归调用失败

时间:2014-01-05 16:04:13

标签: javascript recursion promise

我刚刚写道:

function getQtyFor(state,down) {
  var promise = new RSVP.Promise( function (fulfill, reject) {
      if (!down && (state=='bottle' || state=='pumped')) {
        doDialog('volume')
          .then ( validateVolume ,
                  function ()    { hideDialog('volume');
                                   return getQtyFor(state,down);     } )
          .then ( function (q)   { hideDialog('volume'); 
                                   fulfill(q); },           
                  function (e)   { hideDialog('volume');
                                   alert("Bad input "+e); 
                                   return getQtyFor(state,down);       } )
      } else fulfill(0);
  });
  return promise; 
}

您可以在其中看到两个递归调用。我发现第一个按预期工作,第二个按预期进行循环,但是在使用第二个之后我永远不会得到“实现”。换句话说,我可以通过取消对话框(第一次递归)或输入验证器不喜欢的值(第二次递归)来绕圈运行。在前一种情况下,在我最终决定点击OK之后,等待“然后”将运行并删除我的数据库中的东西。但是如果我通过输入愚蠢的值然后输入一个合理的值来绕圈,那么等待的“那么”将不会运行,也不会是拒绝处理程序。

我有点怀疑问题是我履行的承诺与我的处理程序附带的承诺不同,但我仍然不明白为什么它以某种方式工作而不是另一种方式。

我猜你需要剩下的代码才能重现这个,所以它在http://quorve.com/rsvpissue/babylog.html。这是前面提到的等待“然后”:

function stick(down) {
  return function(ob) {
    return getQtyFor(ob.attr('id'), down)
    .then( getStickyFields(down, ob), alert ) //NEITHER REACHED AFTER FAILED VALIDATE
    .then( db_insert('transitions') )                         
    .then( function() { updateButtonAppearance(down)(ob); } , alert);
  }
}

从有问题的递归函数调用的东西:

function doDialog(log) {
  var promise = new RSVP.Promise( function(fulfill, reject) {
    $('#'+log).dialog({
      dialogClass: "no-close",
      modal: true,
      buttons: {
        "OK":     function() { fulfill($(this)); },
        "Cancel": function() { reject(); }
      }
    });
  });
  return promise;
}

function validateVolume(form) {
  vol = form.find("[name=qty]").val();
  if ( vol > 200 ) { 
    throw("vol"); }
  return vol;
}

重现的步骤:

使用Chrome使用WebSQL。 (我知道它被解雇了,但是我们不要改变主题。)

转到http://quorve.com/rsvpissue/babylog.html

单击Zach的瓶子(按下按钮),然后在对话框中单击取消。对话框一直持续到你点击OK,之后,你会看到一个新的过渡,右下角代表饮酒会话的结束,数量为150ml。当您按取消时,您正在使用第一个递归调用。

重新加载页面(重置数据库。)像以前一样点击瓶子,但将滑块推到顶部(没有婴儿可以喝那么多),然后按OK。关闭唠叨框并再次出现对话框。如果你愿意,重复一遍将滑块推到较低的值,然后按OK。现在你看到了问题:对话框消失了,所以我们退出了递归,但是按钮和DB没有更新,因为没有调用继续,也没有被拒绝的情况。

这是RSVP中的错误还是我误解了承诺?

TIA,Adrian。

1 个答案:

答案 0 :(得分:2)

怀疑它!我应该说:

fulfill(getQtyFor(state,down))

而不是

return getQtyFor(state,down)

用于递归调用。