【问题标题】:What's the explanation for this behavior: ES6 Promise that is never resolved这种行为的解释是什么:ES6 Promise that never resolve
【发布时间】:2019-03-07 20:54:33
【问题描述】:

以下代码:

Promise.resolve('a string')
  .then(resp => {
    console.log('resp from the initial promise: ' + resp)
    const p0 = new Promise((resolve, reject) => {
      setTimeout(() => {
        console.log('finished sleeping in p0')
        resolve('hello from p0')
      }, 5000)
    })
    console.log('returning p0')
    return p0
  })
  .then(resp => {
    console.log('resp from p0: ' + resp)
    const p1 = new Promise((resolve, reject) => {
      console.log('p1 completed')
      // resolve('another string from p1')
    })
    console.log('returning p1')
    return p1
  })
  .then(res => {
    console.log('resp from p1: ' + res)
  })
  .catch(err => {
    console.error('Error: ' + err.message)
  })

console.log('last statement')

当我运行它时,我得到以下输出(这对我来说没有意义)

last statement
resp from the initial promise: a string
returning p0
finished sleeping in p0
resp from p0: hello from p0
p1 completed
returning p1

首先,由于承诺p1 永远不会解决,我希望程序永远等待并且永远不会完成。事实并非如此,它完成得很好(尽管没有到达最后一个then())。

此外,它还创建了 Promise 并执行了 Promise 中的代码创建之后的代码之前。我希望“返回 p1”“p1 完成”之前出现,因为我认为承诺中的内容将在下一个滴答时执行。

【问题讨论】:

  • p1 永远无法解决.. 自我解释。
  • 所以,呃,想想你在哪里打电话console.log('p1 completed')
  • @StevenStark 我假设如果 p1 从未解决,则承诺链将永远等待它解决。显然情况似乎并非如此,但我想要更多解释为什么会这样。在我看来,做出承诺意味着你想等到它完成,这似乎是合理的。如果它永远无法完成,为什么程序会结束?
  • 为什么看起来不是这样?链条不会继续。

标签: javascript node.js promise es6-promise


【解决方案1】:

此外,它会创建 Promise 并在创建后的代码之前执行 Promise 内的代码。我希望 'returning p1' 会在 'p1 completed' 之前出现,因为我假设 promise 中的内容将在下一个滴答时执行。

如果你在 promise 上调用.then,你传入的函数将被延迟到下一个tick。但是 Promise 的构造函数不会那样做。当您构造new Promise 时,您传递给构造函数的代码会立即同步运行。所以这段代码:

const p0 = new Promise((resolve, reject) => {
  setTimeout(() => {
    console.log('finished sleeping in p0')
    resolve('hello from p0')
  }, 5000)
})
console.log('returning p0')

... 将立即设置超时,甚至在 Promise 被分配给 p0 之前。而这段代码:

const p1 = new Promise((resolve, reject) => {
  console.log('p1 completed')
  // resolve('another string from p1')
})
console.log('returning p1')

... 将立即注销“p1 完成”,甚至在承诺被分配给p1 之前。

【讨论】:

  • 我还要提一下,由于resolverejectp1 已经超出范围,所以p1 一旦从.then() 回调中返回就可以被垃圾回收,允许事件循环终止,因为没有更多的预定滴答声。
  • 虽然我只是做了一个快速测试。有趣的是,即使resolve 还没有超出范围,如果setTimeout()unref()'d,程序仍然会提前终止。我想这意味着事件循环不会强烈引用仍然有可能解决的未决承诺......这对我来说似乎是个问题。
猜你喜欢
  • 1970-01-01
  • 2012-01-24
  • 2013-08-07
  • 2019-01-20
  • 1970-01-01
  • 1970-01-01
  • 2018-10-10
  • 2012-03-16
  • 1970-01-01
相关资源
最近更新 更多