why when I resolve a promise, the output is in pending state?

77 views Asked by At

so consider the code below, when I resolve a promise the result is in pending state in the very first moment( I know after I expand the dropdown I will see the expected result but in here I'm questioning the very first moment), while I reject a promise, it shows the expected result in very first moment. so I wonder why is this happening?

code:

 const test = new Promise((resolve, reject) => {
 resolve(Promise.resolve(78))
 })

 console.log(test);

 //output in console:Promise {<pending>}
 const test2 = new Promise((resolve, reject) => {
 reject(Promise.resolve(78))
 })
 
 console.log(test2);

 //output:promiseĀ {<rejected>: Promise}
3

There are 3 answers

3
Alexander Nenashev On BEST ANSWER

From MDN:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/Promise#return_value

Note that if you call resolveFunc or rejectFunc and pass another Promise object as an argument, it can be said to be "resolved", but still not "settled". See the Promise description for more explanation.

The returned promise is settled async so we should create a microtask async to aim to the point when the returned promise is settled:

const test = new Promise((resolve, reject) => {
  resolve(Promise.resolve(78))
})

queueMicrotask(() => queueMicrotask(() => console.log(test)));

enter image description here

3
Alexander Burov On

The Promise is literally a promise: a promise to provide some value later, once some work is done. So to get a value you should either await it, or provide a callback by using then / catch methods.

Basically, when you have that test const:

const test = new Promise((resolve, reject) => {
    resolve(Promise.resolve(78)); // or reject(Promise.resolve(78));
})

You have two valid options to write deterministic code:

// Use callbacks:
test
    .then(result => console.log("It's for sure successfully completed."))
    .catch(e => console.log("It's for sure failed at this moment."));

// Use await:
try {
    const result = await test;
    console.log("It's for sure successfully completed.")
} catch (e) {
    console.log("It's for sure failed at this moment.")
}

What you're observing is just result of some internal implementation, you should not rely on that observation. This actual result could change in other JavaScript engines or in different versions.

0
traktor On

Promise resolution

The technical explanation is that pairs of resolve/reject functions are "one shots" in that once you call one of them, further calls to either function of the pair are ignored without error.

If you resolve a promise with a promise or thenable object, Promise code internally creates a new, second pair of resolve/reject functions for the promise being resolved and adds a then clause to the resolving promise to resolve or reject the promise being resolved, according to the settled state of the resolving promise.

Namely, in

const test = new Promise((resolve, reject) => {
 resolve(Promise.resolve(78))
})

resolve(Promise.resolve(78)) conceptually becomes

Promise.resolve(78).then(resolve2,reject2)

where resolve2/reject2 are a new pair of resolve/reject functions created for the promise test.

If and when executed, one of the then clause's handlers (namely resolve2 in this case) will be called by a Promise Reaction Job placed in the microtask queue. Jobs in the microtask queue are executed asynchonously to calling code, where test will remain pending at least until after the synchronous code returns.

Note in summary: you can only settle a promise with a non-promise value.

Promise Rejection

Promise rejection is certain if a promise's reject function is called. Hence you can reject a promise with any JavaScript value, including a Promise object in any state.

Namely in

const test2 = new Promise((resolve, reject) => {
 reject(Promise.resolve(78))
 })

the rejection can be performed synchronously, and the the rejection reason of test2 is the promise object Promise.resolve(78), not the number 78. Demo:

const test2 = new Promise((resolve, reject) => {
 reject(Promise.resolve(78))
 })

test2.catch(reason => 
   console.log("reason is a promise: ", reason instanceof Promise)
);