【问题标题】:Why a promise is pending when there is an object with key name "then"为什么当存在键名为“then”的对象时,promise 处于未决状态
【发布时间】:2019-04-19 23:25:56
【问题描述】:

JavaScript 在以下情况下工作异常。

我看到了这个答案并得到了这个关于 Javascript 奇怪行为的问题:https://stackoverflow.com/a/50173415/1614973

我发现如果我们将他代码中的then 更改为任何其他键名,我们将得到完全不同的结果。 CodePen 演示:hischanged

我试过 Chrome 和 Firefox,他们都有这个问题。 我在那里探索了问题并找到了这个“错误”的一些基本规则。

// This one will always pending
const pendingPromise = Promise.resolve(x=>x).then(r => ({ then: y => 0 }));
pendingPromise.then(r => console.log("promise resolved")); // "promise resolved" will never logged

// Thanks @Jaromanda X's correction. a simpler version is:
const pendingPromise1 = Promise.resolve().then(() => ({then: y => 0}))
pendingPromise1.then(r => console.log("promise1 resolved")); // "promise1 resolved" will never logged

pendingPromise 永远处于等待状态。据我所知,有三件事可以切换此错误:

  1. 原来的必须用函数来实现。(不必要的约束)
  2. .then 中,必须返回一个键名为“then”的对象。
  3. then 键的值必须是函数。

我想知道为什么会发生这种情况。

【问题讨论】:

  • x=>xr 完全不相关,所以第 1 点是错误的……pendingPromise = Promise.resolve().then(()=>({then: y => 0})) 的行为相同
  • 您可以通过阅读 then 方法应该如何实现promisesaplus.com/#the-then-method 来了解您的错误
  • @Jaromanda X 你是对的。感谢您的更正。我已经改变了我的问题。

标签: javascript promise


【解决方案1】:

它永远不会解决的原因是因为你最后的“then”永远不会调用resolve:

.then(r=>({then: y => 0})) 只是返回一个不可调用的0

y 是一个解析回调。要使您的代码正常工作,请将y 更改为resolve,然后调用它。或者,只需致电y。重点是,在调用 resolve 之前,promise 一直处于未决状态。

console.log("Starting Strange Promise")
const pendingPromise = Promise.resolve(x=>x).then(r=>(
  {then: y => "Strange Promise Done!"}
));
pendingPromise.then(console.log) // never happens

console.log("Starting Hacked Promise")
const hackedPromise = Promise.resolve(x=>x).then(r=>(
  {then: resolve => resolve("Hacked Promise Done!")}
));
hackedPromise.then(console.log)  // happens, like, speed of light quickly

【讨论】:

  • 为了避免一些混淆,它不必被称为resolve ...它可以被称为任何东西,因为它是onresolved回调(两个之一)传递给然后...因此原始代码只需为{then: y => y(0)}
【解决方案2】:

我们都熟悉这一点:在其中一个.then(callback) 中,如果回调返回另一个承诺,比如lastPromise,整个承诺链(直到那时)将有效地“变成”lastPromise

在内部,promise 链根本不检查lastPromise 是否是一个真正的promise。它只检查它是否实现了 thenable 接口(有一个.then() 方法)。如果是,那么它进一步假设该方法也符合spec

promise 必须提供 then 方法来访问其当前或最终值或原因。

promise 的 then 方法接受两个参数:

promise.then(onFulfilled, onRejected)

现在,您从回调中返回一个对象,该对象具有 .then 方法,这使其成为 thenable。因此,promise 链会将这个对象视为同志,相信它是一个“promise”,调用它的.then(onFulfilled, onRejected)(实际上是(resolve, reject) 对)。

现在一个优秀的 thenable 知道如何处理 (onFulfilled, onRejected) 是正确的。不幸的是,他们相信了错误的人。你的实现如下:

then = (onFulfilled) => 0

你从来没有真正调用onFulfilled(someValue) 来解决挂起状态,所以由于整个链现在“变成”lastPromise,但是你的假lastPromise 无法解析/拒绝,整个链只是停留在挂起状态不错。

这就是盲目相信任何可以成为承诺的可悲故事。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-07-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-22
    • 2022-11-19
    • 1970-01-01
    • 2020-04-11
    相关资源
    最近更新 更多