当前位置: 首页 > 面试题库 >

承诺回调返回承诺

武成和
2023-03-14
问题内容

关于这两个重要来源:NZakas-
承诺链中的归还承诺
和MDN承诺,我想提出以下问题:

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

例如,

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的实现处理程序。即使是这里的句子也令人困惑。

您能给我解释一下这到底是怎么回事吗?我对这个概念感到困惑。


问题答案:

假设在then()回调then()函数内部抛出结果会导致失败,并从失败中返回,而从回调函数中返回则实现了成功值。

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

但是,如果我在那里进行异步工作,那么对return或来说为时已晚throw,不是吗?

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对象。然而,通过返回p2then()产生p3你说
“我想要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
  })
}

同样,这是非常伪的代码,但显示了如何then()在Promise实现中实现的背后思想。

如果我们想增加对解决Promise的支持,我们只需要修改代码以callbackthen()返回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实现如何处理此问题。



 类似资料:
  • 问题内容: 我正在使用promis模块从请求模块返回我的json数据,但是每次运行它时,它都会为我提供此信息。 我无法正常工作,有人知道这个问题吗?这是我的代码: 问题答案: 许诺是充当未来价值的占位符的对象。您的函数返回该Promise对象。通过将处理程序附加到promise,您可以在promise中获得未来的价值: 这是异步代码,因此,仅能通过处理程序来获得承诺的价值。 修改清单: 在返回的p

  • 问题内容: 我有一个像这样的递归函数 我正在使用它 我注意到您好永远不会返回,因为我怀疑我在递归调用上创建了多个promise,但是我不确定如何从中返回。 如何返回每个递归创建的Promise? 编辑: 结果是 问题答案: 递归是一种功能性遗产,因此将其与功能性样式一起使用可产生最佳效果。这意味着编写接受和操作其输入(而不是依赖于外部状态)和返回值(而不是依赖于突变或副作用)的函数。 你的程序,而

  • 问题内容: 无论我的Promise是否成功解决,我都想执行相同的操作。我不想将相同的功能绑定到两个参数。没有像jQuery一样的东西吗?如果没有,我该如何实现? 问题答案: 没有像jQuery一样的东西吗? 如果没有,我该如何实现? 您可以这样实现自己的方法: 或更广泛地讲,将解析信息传递给回调: 两者都确保原始解析得以维持(当回调中没有异常时),并确保等待诺言。

  • 问题内容: 我已经开发JavaScript几年了,我完全不了解关于promise的麻烦。 看来我所做的就是改变: 无论如何我都可以使用像async这样的库,它有类似以下内容: 哪个代码更多,可读性更差。我在这里什么都没得到,也不是突然变得神奇地“平坦”。更不用说必须将事情变成诺言。 那么,这里的诺言有什么大惊小怪的呢? 问题答案: 承诺不是回调。许诺代表 异步操作 的 未来结果 。当然,以您的方式

  • 本文向大家介绍承诺回调和异步/等待,包括了承诺回调和异步/等待的使用技巧和注意事项,需要的朋友参考一下 首先,我们必须了解两个主要概念 同步编程 异步编程 同步编程 它等待每个语句完成执行,然后再转到下一条语句。 如果语句不相互依赖,但是由于它们在队列中,它们仍在等待执行,则此方法可能会减慢应用程序的速度。 异步编程 在移动到下一条语句之前,它不等待当前语句完成执行。例如,调用Web服务并使用Ja

  • 问题内容: 我知道您不能使异步函数同步运行,但是如何向我的promise链添加某种顺序? 一个结果依赖于先前的promise值,当不发生时,我得到一个未定义的错误。这是一个http请求,因此它依赖于外部因素,例如我的连接执行请求的速度等。 我正在按以下方式调用上述方法。但是console.log返回未定义。 终端打印 问题答案: 尝试从第一个然后回调的返回promise