(Related but not quite the same: JS Promises: Fulfill vs Resolve)
I\'ve been trying to wrap my head around Javascript promises, and I\'m struggling with the basic no
Let's add emphasis somewhere else in one of your quotes :
A promise is resolved if trying to resolve or reject it has no effect, i.e. the promise has been "locked in" to either follow another promise, or has been fulfilled or rejected
reject()
will change your Promise and all the prior-chained ones status to rejected
.
While resolve()
will lock your current Promise, but only the fulfillment of the resolving callbacks will set its status to fulfilled
. As long as everything is not finished, your Promise will still be 'pending'
.
e.g If you do chain your Promise, and that during the chain, an error is thrown, then the state of your Promise is set to 'rejected'
.
var p = new Promise((resolve, reject) => {
resolve(); // here p is resolved, we can't call resolve() or reject() anymore
}).then((e) => { // chain it
return new Promise((resolve, reject) => {
console.log(p); // 'pending' because it's still chained
reject('whatever') // this one throws an error and breaks the chain
})
}).then(() => console.log('passed')); // won't happen
setTimeout(() => console.log(p, "please check in your browser's console"), 1000); // rejected
So even if you are resolve()
-ing the current operation of your Promise, you can't know what will happen after, so you can't know if at the end it will be fulfilled
or rejected
.
I'm struggling with the basic notions of resolve and resolved, vs. fulfill and fulfilled.
Have a look at What is the correct terminology for javascript promises. Yes, they're sometimes mixed up, but let's try to ignore that.
Yet the spec refers to the first argument to the
then()
method (or its corresponding abstract concepts) using both fulfill and resolve. Did we end up with the documents that are supposed to be the guiding lights of the movement using terms in inconsistent ways?
No, there is no inconsistency here, the terms in the spec are accurate.
resolve is not the opposite of reject, and the onFulfilled
callback does not exactly correspond to resolving.
Or is there something I'm missing, and resolve is actually a more appropriate term than fulfill for what the
resolve()
method does?
Yes. The problem is that you can resolve with a promise (or in general, a thenable, i.e. any object with a then
method), and instead of fulfilling with that object the resolved promise will try to fulfill with the thenable's result. Or when the thenable has (will have) an error, it will reject with that as the reason.
There is no mention [in MDN] of the
Promise.resolve()
method having the potential to reject.
Actually there is: "the returned promise will "follow" that thenable, adopting its eventual state". If that eventual state is the error state, then the returned promise will reject as well.
There is a
Promise.reject()
method, but noPromise.fulfill()
method. So here, the counterpart to reject is resolve, instead of fulfill.
Yes, ES6 promises are lacking a Promise.fulfill
method. This is a bit inconsistent and confusing at first, but was done for a good reason: It prevents you from having a promise that is fulfilled with another promise. You can only resolve ES6 promises, and when you pass in a promise it will take its result not the promise object by itself.
This is pretty useful, but can be pretty inconvenient as well. There are libraries that do it better and allow this case, they're so-called "algebraic promises" (which you can reason about a lot better). Creed is a good example of that, and its Promise.of
method is a real counterpart to Promise.reject
.