What happens if I decline a promise with a different Promise value?

If Promise p enabled with a Promise (or Thenable) q value, it essentially becomes a copy of Promise q . If q allowed, p will be allowed with the same value.

 Promise.resolve(Promise.resolve("hello")); 
 Promise {[[PromiseStatus]]: "resolved", [[PromiseValue]]: "hello"} 

If q rejected, p will be rejected with the same value.

 Promise.resolve(Promise.reject(new Error("goodbye"))); 
 Promise {[[PromiseStatus]]: "rejected", [[PromiseValue]]: Error: goodbye} 

The fact that Promise p was allowed / rejected through Promise q , and not directly with the corresponding value, is not related to the final result. Intermediate Promise is consumed as part of the resolution process and is not visible to the consumer.

If q never allowed or rejected, p will also remain forever.

 Promise.resolve(new Promise(() => null)); // perpetually-pending promise 
 Promise {[[PromiseStatus]]: "pending", [[PromiseValue]]: undefined} 

These cases are well known, but I have never seen what happens if Promise is rejected (and not allowed) with a different Promise value. Does the deviation process affect intermediate Promises, or are they transmitted unchanged?

If he consumes them, how does it work?

+5
source share
4 answers

Let's see what happens if we reject Promise p with the promise q resolved:

 Promise.reject(Promise.resolve("hello")); 
 Promise {[[PromiseStatus]]: "rejected", [[PromiseValue]]: Promise} Uncaught (in promise) Promise { [[PromiseStatus]]: "resolved", [[PromiseValue]]: "hello"} 

Or more explicitly:

 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"} 

Promise q , the deviation value is never unpacked! p Deviation handlers are called with Promise q , not with the value contained in it.

This also means that the deviation handler p does not have to wait until q is resolved before it starts. Even if q never resolved, the p deviation handler can still be called.

 Promise.reject(new Promise(() => null)); // Reject with perpetually-pending Promise 
 Promise {[[PromiseStatus]]: "rejected", [[PromiseValue]]: Promise} Uncaught (in promise) Promise { [[PromiseStatus]]: "pending", [[PromiseValue]]: undefined} 

Finally, let me confirm the behavior if we reject Promise p using another rejected promise 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} 

We again see that q does not expand, and p the deviation handler will be called with q itself, and not with the value that q was rejected with.

+7
source

So Jeremy answers what happens:

 const p = Promise.reject(Promise.resolve(3)); 

p is a rejected promise with a negative value of a Promise of 3.

We have been taught to believe that promises will never be resolved with promises! Well, this is a special case. Here we reject the promise with another promise contrary to what then does.

But why?!?

Easy to sport there. Let me first omit some terminology.

The promised beginning as expected , it can either become:

  • done - mark completed with value.
  • rejected - flagging failed for a reason.

So far so good, but consider two additional terms:

  • allowed - this means that he has decided a different meaning of the promise and is tracking it.
  • sett - this means that it is truly fulfilled or rejected - either through a promise that it has resolved, or by itself.

Phew Now this one:

What Promise.resolve does creates a promise resolved to a different value. If this value is the promise that it keeps track of, then otherwise it is immediately set with the value passed. This also happens if you return from inside then or await something in the async function.

What Promise.reject does creates a promise rejected by another value. He has no chance to follow another promise, because it is immediately created with a rejected result.

This behavior is specified in reject and resolve . In particular, we create the promise opportunity and resolve is special - namely, take a look at the "Promise Resolution Functions".

Well, you told me what was going on, but why?!?!?!?

Ok, consider alternatives. We want resolve simulate a return from then or expect in the async function and reject to simulate throw ing in then or in the async function.

 const p = Promise.resolve().then(() => { throw Promise.reject(5); }); 

Clearly, resolving p to 5 does not make sense! We noted that the promise was fulfilled correctly, but it clearly did not end correctly.

Similarly:

asynchronous function foo () {quit Promise.resolve (5); } Foo (); // no one expected a solution to foo .

How about a deviation with an expanded value?

This would mean that we are losing information about what kind of denial we are dealing with. The only alternative is to reject using the Promise object.

Should I ever run into this?

No never. You should never throw promises anyway, and you should always reject using Error s .

+5
source

Creating a Promise Object:

  new Promise( executor) 

calls the executing function with two arguments to the callback function:

  executor( resolve, reject) 

where resolve overloaded by type of argument on

  • link promise thenable :

     resolve( thenable); // link the resolved promise to the final state of the thenable. 

    where the permitted promise remains pending until the promise with which it is associated (“has been resolved with”) is reached, or

  • keep a promise with something that is not thenable

      resolve (notThenable); // fulfill the promise with anything except a thenable. 

Being javascript, “overloaded” in this context is accomplished by checking the type and properties of the argument for resolve at run time, rather than compiling the script. A simplified explanation is that you cannot fulfill a promise with a promise or promise as an object.

The reject function is not overloaded and does not check its argument at run time. If a promise is rejected with a promise or other thenable , it is treated as any other reason for rejection. The promise does not remain pending and is rejected. The promise used for rejection is passed as an argument to the reason for any function that catches the promise. The simplified explanation is that you can refuse a promise with anything, but if it is not an Error object or a descriptive reason, you are on your own!

+3
source

Promise.resolve () can take a value, then either a promise. He adapts his behavior.

Promise.reject () takes only an immediate value. Therefore, if you give him a promise, he will clumsily try to consider it as a direct meaning.

However, you will not take advantage of the promise by passing it to Promise.reject . You can do it:

 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 
-1
source

All Articles