如果使用Promise(或Thenable)p
的值解析Promise q
,它实际上会成为Promise q
的副本。如果q
已解决,则p
将使用相同的值进行解析。
Promise.resolve(Promise.resolve("hello"));
Promise {[[PromiseStatus]]: "resolved", [[PromiseValue]]: "hello"}
如果q
被拒绝,则p
将被拒绝并使用相同的值。
Promise.resolve(Promise.reject(new Error("goodbye")));
Promise {[[PromiseStatus]]: "rejected", [[PromiseValue]]: Error: goodbye}
通过Promise p
解决/拒绝承诺q
而不是直接使用相应的值,这与最终结果无关。中间Promise作为解决过程的一部分被消费,并且对消费者不可见。
如果q
永远不会被解决或被拒绝,p
也将永远保持待审。
Promise.resolve(new Promise(() => null)); // perpetually-pending promise
Promise {[[PromiseStatus]]: "pending", [[PromiseValue]]: undefined}
这些案例众所周知,但我从未见过如果Promise被拒绝(而不是已解决)与另一个Promise值会发生什么。拒绝过程是否也消耗中间承诺,或者它们是否完整传递?
如果确实消耗了它们,那该怎么办?
答案 0 :(得分:7)
让我们看看如果我们拒绝承诺已解决的承诺p
的承诺q
会发生什么:
Promise.reject(Promise.resolve("hello"));
Promise {[[PromiseStatus]]: "rejected", [[PromiseValue]]: Promise}
Uncaught (in promise) Promise {
[[PromiseStatus]]: "resolved", [[PromiseValue]]: "hello"}
或更明确地说:
const q = Promise.resolve("hello");
const p = Promise.reject(q);
p.then(null, x => console.log("Rejection value:", x));
Rejection value: Promise {[[PromiseStatus]]: "resolved", [[PromiseValue]]: "hello"}
承诺q
,拒绝价值,永远不会被解开! p
的拒绝处理程序使用Promise q
本身调用,而不是它包含的价值。
这也意味着p
的拒绝处理程序在运行之前不需要等待q
被解析。即使永远无法解析q
,仍然可以调用p
的拒绝处理程序。
Promise.reject(new Promise(() => null)); // Reject with perpetually-pending Promise
Promise {[[PromiseStatus]]: "rejected", [[PromiseValue]]: Promise}
Uncaught (in promise) Promise {
[[PromiseStatus]]: "pending", [[PromiseValue]]: undefined}
最后,如果我们使用另一个被拒绝的承诺p
拒绝承诺q
,请让我们确认行为:
Promise.reject(Promise.reject(new Error("goodbye")));
Promise {[[PromiseStatus]]: "rejected", [[PromiseValue]]: Promise}
Uncaught (in promise) Error: goodbye(…)(anonymous function)
Uncaught (in promise) Promise {[[PromiseStatus]]: "rejected", [[PromiseValue]]: Error: goodbye}
我们再次看到q
未展开,p
的拒绝处理程序将使用q
本身进行调用,而不是q
被拒绝的值
答案 1 :(得分:5)
所以,Jeremy的回答解释了会发生什么:
const p = Promise.reject(Promise.resolve(3));
p
是被拒绝的承诺,拒绝价值Promise
为3。
我们被教导相信承诺永远不会兑现承诺!嗯,这是一个特例。在这里,我们拒绝承诺与另一个承诺相矛盾的then
。
轻松运动。让我们先来看一些术语。
承诺从待处理开始,它可以成为:
到目前为止一切顺利,但让我们考虑另外两个术语:
呼。现在已经开始了:
Promise.resolve
所做的是创建一个承诺已解决到另一个值。如果该值是一个承诺,它会跟踪它 - 否则它会立即与传入的值结算。如果您return
或then
内的await
async
,也会发生这种情况。 {1}}功能。
Promise.reject
做的是使用其他值创建承诺被拒绝。它没有机会遵循另一个承诺,因为它会立即被拒绝的结果创建。
此行为在reject
和resolve
中指定。特别是 - 我们正在创建promise capability和resolve
is special - 即查看" Promise Resolve Functions"。
好吧,让我们考虑其他选择。我们希望resolve
模仿从then
返回或等待async
函数和reject
来模仿throw
或then
中的async
const p = Promise.resolve().then(() => {
throw Promise.reject(5);
});
函数。
p
更清楚地看到将foo
解析为5毫无意义!我们将承诺标记为正确完成,但显然没有正确完成。
类似地:
async function foo(){
抛出Promise.resolve(5);
}
FOO(); //没有人希望Promise
能够解决。
这意味着我们会丢失有关我们正在处理哪些拒绝的信息。唯一的选择是使用throw
对象拒绝。
不,永远不会。你永远不应该SlideMenuController
承诺,你应该始终reject with Error
s。
答案 2 :(得分:3)
承诺对象构建:
new Promise( executor)
使用两个回调函数参数调用执行程序函数:
executor( resolve, reject)
其中resolve
被参数类型重载为
链接对thenable
的承诺:
resolve( thenable); // link the resolved promise to the final state of the thenable.
已解决的承诺保持挂起状态,直到与其关联的承诺("已通过"解决)已解决,或
履行承诺的内容不是thenable
resolve (notThenable); // fulfill the promise with anything except a thenable.
成为javascript,"重载"在此上下文中,通过resolve
在运行时检查参数类型和属性来执行,而不是在编译脚本时执行。 一个简单的解释是,您无法履行承诺或承诺之类的承诺。
reject
函数没有重载,也没有在运行时检查它的参数。如果承诺被承诺或其他thenable
拒绝,则将其视为任何其他拒绝原因。承诺不会继续等待并被拒绝。用于拒绝的承诺作为理由参数传递给任何捕获承诺拒绝的函数。 一个简单的解释是,您可以拒绝任何您喜欢的承诺,但如果它不是Error
对象或描述性原因,那么您就是自己!
答案 3 :(得分:-1)
Promise.resolve()可以获取价值,价值或承诺。它适应了它的行为。
Promise.reject()只占一个直接值。因此,如果您将Promise传递给它,它将会笨拙地试图将其视为直接值。
但是,您不会将承诺传递给Promise.reject
。你可以这样做:
Promise.reject(myPromise); // weird and useless, and with no side effect
myPromise.then(e=>{console.log(e)}); // "consume" the promise
myPromise.then(e=>{console.log(e)}); // you can consume it as many times as you want