【问题标题】:Details about Promises; examples有关承诺的详细信息;例子
【发布时间】:2016-04-04 03:28:10
【问题描述】:

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

请考虑一下这段代码。

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')
})

鉴于我对 Promise 的理解,我在很多地方都包含了 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 声称它“无法访问”;听起来很一致。

我不希望在 ender 调用 (//#2) 之后进行控制台调用,因为 ender 毕竟解决了几乎所有 ap 范围的 Promise;退出承诺并退出应用程序也就不足为奇了。

我明白了:

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

问题:这是正确的教训吗?该语言无法识别 Promise 在 ap 范围内的显着性。 “返回”足以离开 ender 范围,但不是 ap 范围。 "resolve('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')”;如果我在 ender 调用之后立即添加“return”,它会让我脱离 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 调用之后立即使用“return”;它删除了 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 打印,因为语言不承认回调块中的“拒绝”或“解决”涵盖了所有可能性;它继续执行不明智地放在那个位置的命令。

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

在更一般的层面上:第一次使用 Promise 的人经常无法理解 Promise 的哪些方面?我们如何才能更有信心正确控制执行流程?有哪些资源对解释这种详细程度特别有用?对于这个更笼统的层面的任何建议,我将不胜感激。

提前致谢...

【问题讨论】:

  • 天啊,认真的???尝试发布相关细节兄弟,而不是整个故事。
  • 你为什么还要使用j
  • 诸如 第一次使用 Promises 的人经常无法理解 Promises 的哪些问题? 对于 Stack Overflow 来说太宽泛了。人们可以就该主题写一本书或很长的文章。这个网站最适合处理一个简洁的问题,在几个段落中给出明确的答案,而不是主要基于意见。此外,对于 Stack Overflow,要求 3rd 方资源被认为是题外话。这个问题需要大量清理或关闭。
  • 问题不是那么广泛。它只需要一点耐心才能通篇阅读。我已经写了两次更长的问题。拜托了伙计们! :)

标签: javascript node.js recursion callback bluebird


【解决方案1】:

这里真正的答案是 rejectresolve简单的回调,并标记 Promise 的拒绝/解决。他们没有修改原始的 JavaScript 工作方式,这是您的假设“我不希望在 ender 调用之后进行控制台调用,因为 ender (//#2) 毕竟解决了实际上是所有 ap 范围;退出 promise 并退出 ap 也就不足为奇了。"

致电rejectresolve 仅表示您将遵守该承诺。这并不意味着您执行此操作的功能将立即退出。所以肯定如果你想这样做 - 使用return

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

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

    console.log(... // you DON'T want this
}

好吧,尽管你不想要它,但你肯定会得到它。您创建了一个 if 语句,在其中执行了一些 Promise 魔术,然后使用 console.log。所以 JavaScript 不在乎它是否是 Promise - 它只是一个接一个地执行。

如果你多读一点关于 Promises 的文章,你就会明白它们是纯 JavaScript,里面有一个 try-catch,所以如果抛出错误,它们可以捕获它并调用失败回调(通常提供.catch(function(err){}))。

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

【讨论】:

  • 感谢吨的宽容和答案。我很难理解 Promise 的意外行为。我所有的书中都没有它们。我的网络搜索没有找到这个细节。我的熟人圈子里没有 JavaScript 专家。我同意其他人的观点,即 SO 在回答特定语法问题时效果最好;我不是故意滥用它。我需要另一个指针,比如当我问异步问题时,有人说,“看看 Bluebird!”那人是对的:Promises 好多了,虽然我希望我有更多的文档。
  • 我认为Q's documentation 可能会有所帮助。这只是 Promises 的另一种实现。祝你好运!
  • 返回在 Promise 回调中。所以return 适用于它所保留的特定功能。如果您有function one() { console.log(1); return; console.log(2); } console.log(3) - 您将获得 1 AND 3。返回只会停止记录 2
  • 不会将您从ender返回,它将从.then(function(result, error) {返回:)
  • 回调不从函数伙伴返回 :) 正如我所说 - Promise 是 JavaScript,它不是新语法或其他东西。它只是某种 framework 或更好的说法 - 编程方式。如果您想进一步停止执行该功能 - 您应该使用 return。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-10-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-01
相关资源
最近更新 更多