如果我用另一个Promise值拒绝一个Promise会发生什么?
What happens if I reject a Promise with another Promise value?
如果Promise p
被解析为Promise(或Thenable) 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 q
解析/拒绝Promise p
,而不是直接使用各自的值,这与最终结果无关。中间Promise作为解决过程的一部分被消费,对消费者是不可见的。
如果q
是一个从未解决或拒绝,p
也将永远处于挂起状态。
Promise.resolve(new Promise(() => null)); // perpetually-pending promise
Promise {[[PromiseStatus]]: "pending", [[PromiseValue]]: undefined}
这些情况是众所周知的,但我从来没有见过如果一个Promise被拒绝(而不是用另一个Promise值解决)会发生什么。拒绝过程是否也消耗中间承诺,或者它们是完整地通过的?
如果它确实消耗它们,那是如何工作的?
让我们看看如果我们用已解析的承诺q
拒绝承诺p
会发生什么:
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
的拒绝处理程序使用承诺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}
最后,让我们确认如果我们使用另一个被拒绝的承诺q
拒绝承诺p
的行为:
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
被拒绝的值。
Jeremy的回答解释了发生的事情:
const p = Promise.reject(Promise.resolve(3));
p
是被拒绝的承诺,Promise
的拒绝值为3。
then
相矛盾的承诺来拒绝一个承诺。
为什么? ! ?
放松点。让我们先了解一些术语。
承诺以开头,等待,它可以变成:
- completed -用值标记完成。
- 已拒绝 -标记失败并给出原因。
到目前为止一切顺利,但让我们考虑两个额外的术语:
- resolved -表示已解析到另一个承诺值,并正在跟踪它。
- 已解决 -意味着它实际上已经完成或被拒绝-通过它所解决的承诺或它自己。
唷。现在,这是出路:
Promise.resolve
的作用是创建一个promise ,将解析为另一个值。如果该值是一个承诺,它会跟踪它,否则它会立即处理传入的值。如果在async
函数中从then
或await
中获取return
,也会发生这种情况。
Promise.reject
所做的是用另一个值创建一个promise rejected。它没有机会遵循另一个承诺,因为它是立即创建的,结果是被拒绝的。
此行为在reject
和resolve
中指定。特别是——我们正在创建一个承诺功能,resolve
是特别的——也就是看看"承诺解析函数"。
好吧,你告诉我发生了什么-但是为什么? ? ? ? ? ? ?
好吧,让我们考虑一下其他选择。我们希望resolve
模拟then
的返回或async
函数中的等待,reject
模拟throw
在then
或async
函数中的返回。
const p = Promise.resolve().then(() => {
throw Promise.reject(5);
});
更清楚地看到,将p
解析为5是没有意义的!我们会把承诺标记为正确完成,但它显然没有正确完成。
async函数foo() {把Promise.resolve (5);}foo ();//没有人会期望foo
解析。
拒绝unwrapped值呢?
那就意味着我们失去了处理拒绝的信息。唯一的选择是使用Promise
对象拒绝。
我应该遇到这种情况吗?
没有,从来没有。无论如何,你都不应该使用throw
承诺,而应该使用Error
s拒绝。
承诺对象构造:
new Promise( executor)
使用两个回调函数参数调用executor函数:
executor( resolve, reject)
其中resolve
按参数类型重载为
link对
thenable
的承诺:resolve( thenable); // link the resolved promise to the final state of the thenable.
,在它链接的承诺("was resolved with")被解决之前,已解决的承诺一直处于挂起状态,或者
用非
实现的承诺thenable
resolve (notThenable); // fulfill the promise with anything except a thenable.
作为javascript,在此上下文中的"重载"是由resolve
在运行时检查参数类型和属性来执行的,而不是在编译脚本时执行的。一个简单的解释是,你不能用一个承诺或类似承诺的对象来履行一个承诺。
reject
函数没有重载,也不会在运行时检查它的参数。如果以承诺或其他thenable
拒绝承诺,则将其视为任何其他拒绝理由。承诺不会一直悬而未决,而会被拒绝。用于拒绝的承诺作为reason参数传递给捕获承诺拒绝的任何函数。一个简单的解释是,你可以拒绝任何你喜欢的承诺,但如果它不是一个Error
对象或描述性的原因,你就靠自己了!
promise. resolve()可以接受一个值、一个thenable或一个promise。它适应它的行为。
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
- 将一个方法转换为promise:Nodejs
- 将其中一个异步方法重写为使用promise的方法
- 通过AngularJS promise下载一个文件
- promise.all在一个forEach循环中——所有东西都同时启动
- 多次调用promise函数,直到另一个promise函数满足条件
- 我可以克隆一个Promise吗
- 创建一个空的JavaScript Promise
- 与 promise 一起使用时,异步瀑布不执行下一个回调方法
- 使用 Promise 在另一个函数中调用带有 Bluebird 承诺库的函数
- 如何通过一个回调异步排队和执行多个promise
- 当使用promise时,为什么最后一个会被调用
- 如何访问AngularJS promise链中上一个promise的结果
- Promise.all()方法没有't解析为一个值
- Ember.js:路由返回多个模型,包括一个promise,给出错误
- Promise.promisify不是一个函数
- 在循环中使用 q promise 的最佳方法是什么?等待链完成,然后再迭代到下一个
- 如何使用 Parse.promise javascript 定义一个承诺数组并获取结果数组 [parse.com]
- 使用 Promise.map 返回一个与 bluebird “订购”的对象
- 然后,在前一个完成之前调用 Promise
- Complex Q promise:一个promise创建了一个其他promise的数组