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

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

问题描述

关于这两个很重要的来源: NZakas - 在Promise Chains中回归承诺 MDN承诺,我想问以下内容:

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

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

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.

推荐答案

让我们说扔进然后() callback在失败时拒绝结果promise,从返回then() callback以成功值完成结果promise。

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

但是,如果我在那里进行异步工作,那么返回为时已晚抛出,不是吗?

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

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

这并不意味着在你的例子中 p2 变为 P3 。它们是单独的Promise对象。但是,从返回 p2 然后生成 p3 () >你说我希望 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".

至于 这是怎么发生的,它是特定于实现的。在内部,您可以将然后()视为创建新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实现中实现。

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

如果我们想添加对解析t的支持oa Promise,如果回调你传递给然后(),我们只需修改代码就可以有一个特殊的分支返回了一个Promise:

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天全站免登陆