ChatGPT解决这个技术问题 Extra ChatGPT

then() 返回值或 Promise.resolve 有什么区别

有什么区别:

新承诺(函数(res,rej){ res(“aaa”);}).then(函数(result){返回“bbb”;}).then(函数(result){console.log(result);} );

和这个:

新的 Promise(function(res, rej) { res("aaa"); }) .then(function(result) { return Promise.resolve("bbb"); }) .then(function(result) { console.log (结果); });

我在问,因为我正在使用 Angular 和 $http 服务与链接 .then() 获得不同的行为。代码有点多,因此首先是上面的示例。

你看到了什么“不同的行为”?这两个示例都应该工作并且行为大致相同。第二个示例中的 Promise.resolve() 是不必要的。
@pixelbits 从 then 处理程序返回承诺没有任何问题,事实上,这是承诺规范的一个关键方面,您可以这样做。
在第 2 行中,为什么你必须调用 res("aaa"),为什么不能返回 "aaa" 就足够了,并且 Promise 捕获 resolve() 它的方式与捕获异常的方式相同?
@SamLiddicott 有同样的问题,而地雷则更复杂一些:new Promise((res, rej) => { return fetch('//google.com').then(() => { return "haha"; }) }).then((result) => alert(result)); 此代码只会挂起(不会永远解决)。但是,如果我将 return "haha"; 更改为 return res("haha");,那么它会起作用并提醒“哈哈”。 fetch().then() 不是已经将“哈哈”包装成一个已解决的承诺了吗?
@ShaungCheng 如果使用 Promise 构造函数,则应调用传递的函数的 res 参数,而不是返回结果。返回传递给 Promise 构造函数的函数内部的任何内容都将被忽略

A
Arian Acosta

简单来说,在 then 处理函数内部:

A) 当 x 是一个值(数字、字符串等)时:

return x 等价于 return Promise.resolve(x) throw x 等价于 return Promise.reject(x)

B) 当 x 是已结算的 Promise(不再待处理)时:

如果 Promise 已经解决,return x 等价于 return Promise.resolve(x)。如果 Promise 已经被拒绝,return x 等价于 return Promise.reject(x)。

C) 当 x 是待处理的 Promise 时:

return x 将返回一个待处理的 Promise,并将在随后的 then 中对其进行评估。

Promise.prototype.then() docs 上阅读有关此主题的更多信息。


【B) 2.】应该是“throw x”?
@Lancer.Yan 并非如此,B 表示的是 return 的行为会根据 Promise 的结算值而变化。编写代码时,您真的不知道它是否会解决或拒绝。当然,您可以使用 try-catch 来处理拒绝,然后重新抛出,但这是另一种情况。
C
Community

规则是,如果 then 处理程序中的函数返回一个值,则该承诺会使用该值解析/拒绝,如果该函数返回一个承诺,发生的情况是,下一个 then 子句将是 { 函数返回的 promise 的 1} 子句,因此,在这种情况下,第一个示例不符合 thens 的正常顺序,并按预期打印出值,在第二个示例中,当您执行 Promise.resolve("bbb") 时返回的承诺对象是链接时调用的 then(用于所有意图和目的)。它的实际工作方式将在下面更详细地描述。

引用 Promises/A+ 规范:

承诺解决过程是一个抽象操作,将承诺和值作为输入,我们将其表示为 [[Resolve]](promise, x)。如果 x 是 thenable,它会尝试让 Promise 采用 x 的状态,假设 x 的行为至少有点像 Promise。否则,它以值 x 履行承诺。对 thenables 的这种处理允许 Promise 实现互操作,只要它们公开一个符合 Promises/A+ 的 then 方法。它还允许 Promises/A+ 实现使用合理的 then 方法“吸收”不符合要求的实现。

这里要注意的关键是这一行:

如果 x 是一个承诺,采用它的状态 [3.4] 链接:https://promisesaplus.com/#point-49


“采用其状态”是在 then 处理程序返回承诺时表达行为的一种简洁而有用的方式。 +1 用于规范参考。
实际上 - 这里规范的相关部分是 [[Resolve]]thenables 和 values 上都被调用,所以本质上它用 promise 包装了一个值,所以 return "aaa"return Promise.resolve("aaa")return Promise.resolve("aaa") 相同与 return Promise.resolve(Promise.resolve("aaa")) 相同 - 因为 resolve 是幂等的,在一个值上多次调用它具有相同的结果。
@Benjamin Gruenbaum 是否意味着 return "aaa"return Promise.resolve("aaa") 在任何情况下都可以在 thenables 中互换?
是的,这正是它的意思。
“如果 then 处理程序中的函数返回一个值,则承诺会使用该值解决/拒绝,”我认为答案应该澄清承诺何时解决以及何时拒绝,而不是说“承诺解决/拒绝”。
J
JLRishe

您的两个示例的行为应该几乎相同。

then() 处理程序内返回的值成为从该 then() 返回的承诺的解析值。如果 .then 中返回的值是一个 Promise,则 then() 返回的 Promise 将“采用该 Promise 的状态”并像返回的 Promise 一样解决/拒绝。

在您的第一个示例中,您在第一个 then() 处理程序中返回 "bbb",因此 "bbb" 被传递到下一个 then() 处理程序。

在您的第二个示例中,您返回一个立即使用值 "bbb" 解析的承诺,因此 "bbb" 被传递到下一个 then() 处理程序。 (这里的 Promise.resolve() 是无关的)。

结果是一样的。

如果您可以向我们展示一个实际表现出不同行为的示例,我们可以告诉您为什么会发生这种情况。


不错的答案! Promise.resolve();return; 怎么样?
@FabianTe 这些也将具有相同的效果,除了使用 undefined 而不是 "bbb"
B
Benjamin Gruenbaum

你已经得到了一个很好的正式答案。我想我应该添加一个简短的。

以下内容与 Promises/A+ 承诺相同:

调用 Promise.resolve(在你的 Angular 案例中是 $q.when)

调用 promise 构造函数并在其解析器中解析。在你的情况下,这是新的 $q。

从 then 回调中返回一个值。

在具有值的数组上调用 Promise.all,然后提取该值。

因此,对于 Promise 或纯值 X,以下内容都是相同的:

Promise.resolve(x);
new Promise(function(resolve, reject){ resolve(x); });
Promise.resolve().then(function(){ return x; });
Promise.all([x]).then(function(arr){ return arr[0]; });

毫不奇怪,promise 规范基于 Promise Resolution Procedure,它支持库之间的轻松互操作(如 $q 和本机 Promise),让您的生活更轻松。每当可能发生承诺解决方案时,都会发生解决方案,从而创建整体一致性。


请问做Promise.resolve().then(function(){ return x; });有什么意义?我发现一个片段在做类似的事情(它在 then 块内调用了一个函数)。我认为它或多或少像做超时,但它有点快。 jsben.ch/HIfDo
在 99.99% 的情况下,它与 Promise.resolve(x) 相同是没有意义的。 (0.001% 是我们在对象或代理上的 with 块中,其中 x 属性访问器抛出异常。在这种情况下, Promise.resolve(x) 会导致抛出错误,但 Promise.resolve().then(function(){ return x; }); 会是一个被拒绝的承诺,因为错误是在 then 中引发的)。
你链接了一个空的闪电战,或者你没有保存。无论如何,我不是在谈论陈述之间的差异。我说的正是我写的东西。为了更清楚起见,这是我正在谈论的片段:if (validator) { Promise.resolve().then(() => { this._cdRef.markForCheck(); }); }。这里没有分配承诺,那有什么意义呢?超时是否会(或多或少)产生相同的效果?
它在所有同步代码发生之后但在任何 I/O 发生之前异步执行调用。这就是所谓的“microtick 语义”。
v
vkarpov15

唯一的区别是您在执行 return Promise.resolve("bbb") 时创建了一个不必要的承诺。从 onFulfilled() 处理程序返回承诺会启动 promise resolution。这就是 promise chaining 的工作原理。


u
user2088350

只是一点。正如您在调试器中看到的那样,'resolve' 函数不会返回。如果它是最后一个语句,它似乎会返回。 'Resolve' 会将承诺设置为已完成,但如果下面有更多语句,则继续执行。

如您在此处阅读的:'Why does javascript ES6 Promises continue execution after a resolve?'

这让我很困惑,因为大多数例子都没有解释。所以从现在开始,我必须记住使用“return resolve(value)”或“if resolve(value) else ...other code”,或者只使用“resolve”作为最后一个语句。