承诺回调返回承诺 [英] Promise callbacks returning promises

查看:25
本文介绍了承诺回调返回承诺的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

关于这两个伟大的来源:NZakas - 在承诺链中返回承诺MDN 承诺,我想问以下问题:

With regard to these great two sources: NZakas - Returning Promises in Promise Chains and MDN Promises, I would like to ask the following:

每次我们从承诺履行处理程序返回一个值时,该值如何传递给从同一处理程序返回的新承诺?

Each time that we return a value from a promise fulfillment handler, how is that value passed to the new promise returned from that same handler?

例如

let p1 = new Promise(function(resolve, reject) {
    resolve(42);
});

let p2 = new Promise(function(resolve, reject) {
    resolve(43);
});

let p3 = p1.then(function(value) {
    // first fulfillment handler
    console.log(value);     // 42
    return p2;
});

p3.then(function(value) {
    // second fulfillment handler
    console.log(value);     // 43
});

在这个例子中,p2 是一个承诺.p3 也是源自 p1 的履行处理程序的承诺.但是p2 !== p3.相反,p2 以某种方式神奇地解析为 43(如何?),然后将该值传递给 p3 的履行处理程序.甚至这里的句子也令人困惑.

In this example, p2 is a promise. p3 is also a promise originating from p1's fulfillment handler. However p2 !== p3. Instead p2 somehow magically resolves to 43 (how?) and that value is then passed to p3's fulfillment handler. Even the sentence here is confusing.

你能向我解释一下这里到底发生了什么吗?我完全对这个概念感到困惑.

Could you please explain to me what exactly is going on here? I am totally confused over this concept.

推荐答案

假设在 then() 回调中抛出失败并从 then() 返回的回调拒绝结果承诺 回调以成功值实现结果承诺.

Let’s say that throwing inside then() callback rejects the result promise with a failure, and returning from then() callback fulfills the result promise with a success value.

let p2 = p1.then(() => {
  throw new Error('lol')
})
// p2 was rejected with Error('lol')

let p3 = p1.then(() => {
  return 42
})
// p3 was fulfilled with 42

但有时,即使在延续中,我们也不知道是否成功.我们需要更多时间.

But sometimes, even inside the continuation, we don’t know whether we have succeeded or not. We need more time.

return checkCache().then(cachedValue => {
  if (cachedValue) {
    return cachedValue
  }

  // I want to do some async work here
})

但是,如果我在那里做异步工作,那么 returnthrow 就太晚了,不是吗?

However, if I do async work there, it would be too late to return or throw, wouldn’t it?

return checkCache().then(cachedValue => {
  if (cachedValue) {
    return cachedValue
  }

  fetchData().then(fetchedValue => {
    // Doesn’t make sense: it’s too late to return from outer function by now.
    // What do we do?

    // return fetchedValue
  })
})

这就是为什么如果你不能解析到另一个 Promise,Promises 就没有用处的原因.

This is why Promises wouldn’t be useful if you couldn’t resolve to another Promise.

这并不意味着在您的示例中 p2变成 p3.它们是单独的 Promise 对象.然而,通过从产生 p3then() 返回 p2 你是在说 我想要 p3解析为 p2 解析的任何内容,无论它是成功还是失败".

It doesn’t mean that in your example p2 would become p3. They are separate Promise objects. However, by returning p2 from then() that produces p3 you are saying "I want p3 to resolve to whatever p2 resolves, whether it succeeds or fails".

至于如何,这是特定于实现的.在内部,您可以将 then() 视为创建一个新的 Promise.该实现将能够随时满足或拒绝它.正常情况下,它会在你返回时自动完成或拒绝它:

As for how this happens, it’s implementation-specific. Internally you can think of then() as creating a new Promise. The implementation will be able to fulfill or reject it whenever it likes. Normally, it will automatically fulfill or reject it when you return:

// Warning: this is just an illustration
// and not a real implementation code.
// For example, it completely ignores
// the second then() argument for clarity,
// and completely ignores the Promises/A+
// requirement that continuations are
// run asynchronously.

then(callback) {
  // Save these so we can manipulate
  // the returned Promise when we are ready
  let resolve, reject

  // Imagine this._onFulfilled is an internal
  // queue of code to run after current Promise resolves.
  this._onFulfilled.push(() => {
    let result, error, succeeded
    try {
      // Call your callback!
      result = callback(this._result)
      succeeded = true
    } catch (err) {
      error = err
      succeeded = false
    }

    if (succeeded) {
      // If your callback returned a value,
      // fulfill the returned Promise to it
      resolve(result)
    } else {
      // If your callback threw an error,
      // reject the returned Promise with it
      reject(error)
    }
  })

  // then() returns a Promise
  return new Promise((_resolve, _reject) => {
    resolve = _resolve
    reject = _reject
  })
}

同样,这是非常多的伪代码,但展示了如何在 Promise 实现中实现 then() 背后的想法.

Again, this is very much pseudo-code but shows the idea behind how then() might be implemented in Promise implementations.

如果我们想添加对解析 Promise 的支持,我们只需要修改代码,如果你传递给 then()callback 有一个特殊的分支返回一个承诺:

If we want to add support for resolving to a Promise, we just need to modify the code to have a special branch if the callback you pass to then() returned a Promise:

    if (succeeded) {
      // If your callback returned a value,
      // resolve the returned Promise to it...
      if (typeof result.then === 'function') {
        // ...unless it is a Promise itself,
        // in which case we just pass our internal
        // resolve and reject to then() of that Promise
        result.then(resolve, reject)
      } else {
        resolve(result)
      }
    } else {
      // If your callback threw an error,
      // reject the returned Promise with it
      reject(error)
    }
  })

让我再次澄清一下,这不是一个实际的 Promise 实现,并且有很大的漏洞和不兼容性.然而,它应该让您对 Promise 库如何实现解析为 Promise 有一个直观的了解.在您对这个想法感到满意后,我建议您看看实际的 Promise 实现如何处理这个.

Let me clarify again that this is not an actual Promise implementation and has big holes and incompatibilities. However it should give you an intuitive idea of how Promise libraries implement resolving to a Promise. After you are comfortable with the idea, I would recommend you to take a look at how actual Promise implementations handle this.

这篇关于承诺回调返回承诺的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆