有关承诺的详细信息;例子

Details about Promises; examples

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

请考虑这段代码。

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

鉴于我对 promises 的理解,我在很多地方包含了 console.log 语句,并指出我是否希望它们打印出来。

我预计:

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

我不想在 ender (//#1) 中最后一次调用 console.log,因为它在 return 之后足以让我脱离 ender 范围。我的 linter 声称它是 "unreachable";听起来一致。

我不希望在 ender 调用 (//#2) 之后调用控制台,因为毕竟 ender 解决了几乎所有 ap 范围的 Promise;退出 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 的重要性。 "return" 足以离开 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 调用之后立即添加了一个 return。通过 ender 的唯一路径包括 "return resolve('ender')";如果我在 ender 调用后立即添加 "return",它会让我脱离 bp 范围,一切可能都很好。

考虑到不同的函数名称,我期望得到与我之前预期相同的结果并得到了那个结果。看来我的 "lesson learned" 可能接近正确答案。

接下来我写了这段代码(请忽略对 j 的引用;它们会分散注意力;我想我需要它们来解决后续问题,但第一次没有用,所以 post 更短!):

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

它添加递归并紧跟在 "return" 的 ender 调用之后;它删除了 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 打印是因为该语言无法识别回调块中的 "reject" 或 "resolve" 涵盖了所有可能性;它继续执行不明智地放在那个位置的命令。

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

在更一般的层面上:初次使用 Promises 的人通常不了解 Promises 的哪些方面?我们如何才能更有信心正确控制执行流程?在这种详细程度的解释中,哪些资源特别有用?我将不胜感激关于这个更一般级别的任何建议。

提前致谢...

真正的答案是rejectresolve简单的回调并标记reject/resolve 的承诺。他们不会修改原始的 JavaScript 工作方式,这是您的假设“我不希望在 ender 调用之后调用控制台,因为 ender (//#2) 毕竟,解决了几乎所有 ap 范围的 Promise;退出 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 阻塞您的其他代码,而这根本不会发生:)