I think one principle I take so far is:
A promise is a thenable object, and so it takes the message
then, or in other words, some code can invoke thethenmethod on this object, which is part of the interface, with a fulfillment handler, which is "the next step to take", and a rejection handler, which is "the next step to take if it didn't work out." It is usually good to return a new promise in the fulfillment handler, so that other code can "chain" on it, which is saying, "I will also tell you the next step of action, and the next step of action if you fail, so call one of them when you are done."
However, on a JavaScript.info Promise blog page, it says the fulfillment handler can return any "thenable" object (that means a promise-like object), but this thenable object's interface is
.then(resolve, reject)
which is different from the usual code, because if a fulfillment handler returns a new promise, this thenable object has the interface
.then(fulfillmentHandler, rejectionHandler)
So the code on that page actually gets a resolve and call resolve(someValue). If fulfillmentHandler is not just another name for resolve, then why is this thenable different?
The thenable code on that page:
class Thenable {
constructor(num) {
this.num = num;
}
then(resolve, reject) {
alert(resolve); // function() { native code }
// resolve with this.num*2 after the 1 second
setTimeout(() => resolve(this.num * 2), 1000); // (**)
}
}
new Promise(resolve => resolve(1))
.then(result => {
return new Thenable(result); // (*)
})
.then(alert); // shows 2 after 1000ms
After writing down the whole explanation, the short answer is: it is because the JS promise system passed in a
resolveandrejectas thefulfillmentHandlerandrejectionHandler. The desiredfulfillmentHandlerin this case is aresolve.When we have the code
We can write the same logic, using
The act of returning
pLittlemeans: I am returning a promise, a thenable,pLittle. Now as soon as the receiver gets thispLittle, make sure that when I resolvepLittlewith valuevLittle, your goal is to immediately resolvep2also withvLittle, so the chainable action can go on.How does it do it?
It probably has some code like:
The code above says: when
pLittleis resolved withvLittle, the next action is to resolvep2with the same value.So somehow the system can get
p2Resolve, but inside the system or "blackbox", the function aboveis probably
p2Resolve(this is mainly a guess, as it explains why everything works). So the system doesRemember that
means
passing the resolved value of
pLittletofnand invokefn, sois the same as
which is exactly the same as
** Our goal**above.What it means is, the system passes in a "resolve", as a fulfillment handler. So at this exact moment, the fulfillment handler and the resolve is the same thing.
Note that in the Thenable code in the original question, it does
this
Thenableis not a promise, and you can't resolve it, but since it is not a promise object, that means that promise (likep2) is immediately resolved as a rule of what is being returned, and that's why thethen(p2Resolve)is immediately called.So I think this count on the fact that, the internal implementation of ES6 Promise passes the
p2Resolveintothen()as the first argument, and that's why we can implement any thenable that takes the first argumentresolveand just invokeresolve(v).I think the ES6 specification a lot of time writes out the exact implementation, so we may somehow work with that. If any JavaScript engine works slightly differently, then the results can change. I think in the old days, we were told that we are not supposed to know what happens inside the blackbox and should not count on how it work -- we should only know the interface. So it is still best not to return a thenable that has the interface
then(resolve, reject), but to return a new and authentic promise object that uses the interfacethen(fulfillmentHandler, rejectionHandler).