有什么区别:
新承诺(函数(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()
是不必要的。
then
处理程序返回承诺没有任何问题,事实上,这是承诺规范的一个关键方面,您可以这样做。
new Promise((res, rej) => { return fetch('//google.com').then(() => { return "haha"; }) }).then((result) => alert(result));
此代码只会挂起(不会永远解决)。但是,如果我将 return "haha";
更改为 return res("haha");
,那么它会起作用并提醒“哈哈”。 fetch().then() 不是已经将“哈哈”包装成一个已解决的承诺了吗?
res
参数,而不是返回结果。返回传递给 Promise 构造函数的函数内部的任何内容都将被忽略
简单来说,在 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 上阅读有关此主题的更多信息。
规则是,如果 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]]
在 then
ables 和 values 上都被调用,所以本质上它用 promise 包装了一个值,所以 return "aaa"
与 return Promise.resolve("aaa")
和 return Promise.resolve("aaa")
相同与 return Promise.resolve(Promise.resolve("aaa"))
相同 - 因为 resolve 是幂等的,在一个值上多次调用它具有相同的结果。
"aaa"
和 return Promise.resolve("aaa")
在任何情况下都可以在 then
ables 中互换?
您的两个示例的行为应该几乎相同。
then()
处理程序内返回的值成为从该 then()
返回的承诺的解析值。如果 .then
中返回的值是一个 Promise,则 then()
返回的 Promise 将“采用该 Promise 的状态”并像返回的 Promise 一样解决/拒绝。
在您的第一个示例中,您在第一个 then()
处理程序中返回 "bbb"
,因此 "bbb"
被传递到下一个 then()
处理程序。
在您的第二个示例中,您返回一个立即使用值 "bbb"
解析的承诺,因此 "bbb"
被传递到下一个 then()
处理程序。 (这里的 Promise.resolve()
是无关的)。
结果是一样的。
如果您可以向我们展示一个实际表现出不同行为的示例,我们可以告诉您为什么会发生这种情况。
Promise.resolve();
与 return;
怎么样?
undefined
而不是 "bbb"
。
你已经得到了一个很好的正式答案。我想我应该添加一个简短的。
以下内容与 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
with
块中,其中 x
属性访问器抛出异常。在这种情况下, Promise.resolve(x) 会导致抛出错误,但 Promise.resolve().then(function(){ return x; });
会是一个被拒绝的承诺,因为错误是在 then
中引发的)。
if (validator) { Promise.resolve().then(() => { this._cdRef.markForCheck(); }); }
。这里没有分配承诺,那有什么意义呢?超时是否会(或多或少)产生相同的效果?
唯一的区别是您在执行 return Promise.resolve("bbb")
时创建了一个不必要的承诺。从 onFulfilled()
处理程序返回承诺会启动 promise resolution。这就是 promise chaining 的工作原理。
只是一点。正如您在调试器中看到的那样,'resolve' 函数不会返回。如果它是最后一个语句,它似乎会返回。 'Resolve' 会将承诺设置为已完成,但如果下面有更多语句,则继续执行。
如您在此处阅读的:'Why does javascript ES6 Promises continue execution after a resolve?'
这让我很困惑,因为大多数例子都没有解释。所以从现在开始,我必须记住使用“return resolve(value)”或“if resolve(value) else ...other code”,或者只使用“resolve”作为最后一个语句。
return
的行为会根据 Promise 的结算值而变化。编写代码时,您真的不知道它是否会解决或拒绝。当然,您可以使用 try-catch 来处理拒绝,然后重新抛出,但这是另一种情况。