javascript - promise 回调返回 promise

标签 javascript node.js promise es6-promise

关于这两个伟大的来源:NZakas - Returning Promises in Promise ChainsMDN Promises ,我想问一下:

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

例如,

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 是一个 promise 。 p3 也是一个源自 p1 的履行处理程序的 promise 。但是 p2 !== p3。相反,p2 以某种方式神奇地解析为 43(如何?),然后将该值传递给 p3 的履行处理程序。甚至这里的句子都令人困惑。

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

最佳答案

假设在 then() 回调中抛出一个失败的结果 promise ,并且从 then() 回调返回一个成功值的结果 promise 。

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

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

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

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

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

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,Promise 就没有用处。

这并不意味着在您的示例中 p2变成 p3。它们是独立的 Promise 对象。但是,通过从产生 p3then() 返回 p2 你是在说 “我想要 p3解决任何 p2 解决的问题,无论它是成功还是失败”。

至于如何发生这种情况,这是特定于实现的。在内部,您可以将 then() 视为创建一个新的 Promise。实现将能够随时满足或拒绝它。通常情况下,它会在您返回时自动履行或拒绝:

// 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() 背后的想法。

如果我们想添加对 Promise 解析的支持,我们只需要修改代码以具有一个特殊的分支,如果您传递给 then()callback返回一个 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 实现如何 handle this .

关于javascript - promise 回调返回 promise ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35747957/

相关文章:

javascript - 分配和修改数组之间的区别

javascript - 解析通过 JavaScript 从 AJAX 请求获得的 JSON 响应

javascript - 如何控制2个代码块的执行?

javascript - Node JS - 通过命令行调用js文件函数

javascript - 如何使用 Node Js 编写和检索临时二进制文件?

node.js - connect-mongo session 集合为空

javascript - 如何使用 React 更改 Promise 中的页面

javascript - "Iterating"throw Promise 不允许生成不同的 id

带有异步的自调用函数的 Javascript 语法

Javascript/Jquery - 在函数中设置默认值