关于承诺的细节;实施例

时间:2015-12-30 07:13:48

标签: javascript node.js recursion callback bluebird

我很难实现Promises。 (我认为我理解他们,但我经常得到意想不到的结果,所以也许我不会。)

请考虑这段代码。

function ap() {
  return new Promise(function(resolve, reject) {
    console.log('function ap starting   want this');
    function ender() {
      console.log('function ender starting   want this');
      return resolve('ender');
      console.log('after return in ender   don\'t want this'); //#1
    }
    ender()
    console.log('after function ender and its resolve ' +
      'for Promise   don\'t want this'); //#2
  }) // Promise
} // ap

console.log('---')
ap()
.then(function(result, error) {
  if (error) console.log ('error ' + error.message)
  console.log('function ap result   result=' + result +
    '   want this')
})

我已经在很多地方都包含了console.log语句,并指出我是否希望它们打印出来,因为我对承诺有所了解。

我期待:

function ap starting   want this
function ender starting   want this
function ap result   result=ender   want this

我不想在ender(//#1)中最后一次调用console.log,因为它在返回足以让我离开ender范围之后。我的linter声称它是"无法到达&#34 ;;听起来很一致。

在ender调用(//#2)之后,我不想要控制台调用,因为ender毕竟解决了几乎所有ap范围的Promise;退出承诺并退出ap。并不奇怪。

我得到了:

function ap starting   want this
function ender starting   want this
after function ender and its resolve for Promise   don't want this
function ap result   result=ender   want this

问题:这是正确的教训吗?该语言并未认识到Ap范围内Promise的重要性。 "返回"足以离开ender范围,但不是范围。 "解决(' ender')"足以解决这个承诺。在ender调用之后,执行链继续,这就是打印不需要的语句的原因。程序员必须两者向Promise 发送回调函数,使其超出封闭函数的范围。

继续假设这是真的,我写了这段代码。

function bp() {
  return new Promise(function(resolve, reject) {
    console.log('function bp starting   want this')
    function ender() {
      console.log('function ender starting   want this');
      return resolve('ender');
      console.log('after return in ender   don\'t want this');
    }
    ender(); return;
    console.log('after function ender and its resolve ' +
      'for Promise   don\'t want this');
  }) // Promise
} // bp

它与第一个代码的区别仅在于我在ender调用后立即添加了一个返回。通过ender的唯一途径包括" return resolve(' ender')&#34 ;;如果我添加"返回"在恩德召唤之后,它会立即让我离开bp范围并且一切都很好。

允许使用不同的函数名称,我期望得到与之前预期相同的结果并获得该结果。好像我的经验教训"可能接近正确答案。

接下来我编写了这段代码(请忽略对j的引用;它们会分散注意力;我认为我需要它们来处理后续问题,但这不是第一次工作,使这篇文章更短!):

function cp(i, j) {
  return new Promise(function(resolve, reject) {
    console.log('function cp starting         i=' + i +
      '   j=' + j + '   want this');
    function ender() {
      console.log('function cp ender starting   i=' + i +
        '   j=' + j + '   want this');
      i++;
      let reps = 3;
      if (i < reps) {
        cp(i, j)
        .then(function(result, error) {
          if (error) {
            console.log('*** error   i=' + i +
              '   j=' + j + '   msg=' + error.message +
              '   want this');
            return reject(error);
          }
          console.log('in cp   cp('+ i + ', ' + j +
            ')     result=' + result + '   want this');
          return resolve(result);
        }) // cp(i) callback
        console.log('in cp   i=' + i + '   j=' + j + '' +
          '   in ender after reject, resolve, and ' +
          'callback   don\'t want this'); //#3
      } // if (i < reps)
      console.log('in cp   resolving   i=' + i +
          '   j=' + j + '      want this')
      return resolve('done');
    } // ender
    ender(); return;
    console.log('in cp   i=' + i + '   j=' + j +
      '   after ender call and return for cp scope' +
      '   don\'t want this');
  }) // Promise
} // cp

它添加递归并立即跟随ender调用&#34; return&#34 ;;它删除了linter识别出的无法访问的代码;一切都可能顺利。

我得到了

function cp starting         i=0   j=0   want this
function cp ender starting   i=0   j=0   want this
function cp starting         i=1   j=0   want this
function cp ender starting   i=1   j=0   want this
function cp starting         i=2   j=0   want this
function cp ender starting   i=2   j=0   want this
in cp   resolving   i=3   j=0      want this
in cp   i=2   j=0   in ender after return, resolve, and callback   don't want this
in cp   resolving   i=2   j=0      want this
in cp   i=1   j=0   in ender after return, resolve, and callback   don't want this
in cp   resolving   i=1   j=0      want this
in cp   cp(2, 0)     result=done   want this
in cp   cp(1, 0)     result=done   want this
function cp result   result=done   want this

这是我期望得到的,除了//#3打印,因为语言没有认识到所有可能性都被&#34;拒绝&#34;或者通过&#34;解决&#34;在回调块内;它继续执行不明智的命令。

这些代码位是我仍然遇到问题的程序的模型。很快,我希望能够模拟出让我感到惊讶的其他行为。

在更一般的层面:Promise的第一次定时器经常无法理解Promises?我们怎样才能有更高的信心,我们才能正确控制执行流程?在这个详细程度解释哪些资源特别有用?我会对这个更普遍的建议表示感谢。

提前致谢...

1 个答案:

答案 0 :(得分:2)

这里真正的答案是拒绝解决 简单回调并标记拒绝/解决Promise。他们没有修改原来的JavaScript工作方式,这是你的假设&#34; 我想要在ender调用后想要控制台调用因为ender(//#2),毕竟,解决了几乎所有ap范围的Promise;退出承诺并退出ap。&#34;

并不奇怪

致电rejectresolve只是意味着您将履行该承诺。它并不代表你这样做的功能会马上退出。如果您愿意,肯定 - 请使用return

你的下一个例子也是如此:

if (i < reps) {
    cp(i, j)
    .then(...)

    console.log(... // you DON'T want this
}
好吧,是的,尽管你不想要它,你肯定会得到它。您创建了一个if语句,在其中您执行了一些Promise魔术,然后使用console.log。所以JavaScript并不关心它是否是承诺 - 它只是一个接一个地执行。

如果你仔细阅读Promises,你会发现它们是纯JavaScript,里面有try-catch,所以如果抛出错误,它们就可以捕获它并调用失败回调(通常提供.catch(function(err){}))。

再次 - 承诺不要修改JavaScript的工作方式!你所说的一切都是非常合乎逻辑的,应该确实以恰当的方式发生。而且这是因为你希望Promise阻止你的其他代码,这根本不会发生:)