I found that is possible (in ES6 promises, while Promise object is created) to use multiple resolve/reject which will affect PromiseStatus only once but not affect execution flow.
var p = new Promise(function(resolve, reject) {
setTimeout(function(){
resolve(1);
console.log('Resolve 1');
}, 50);
setTimeout(function(){
resolve(2);
console.log('Resolve 2');
}, 100);
});
setTimeout(function(){
console.log('Status #1:', p);
}, 10);
setTimeout(function(){
console.log('Status #2:', p);
}, 60);
setTimeout(function(){
console.log('Status #3:', p);
}, 110);
p.then(function(x){
console.log('Value after:', x)
})
In then()
functions first resolve/reject will affect execution flow.
So my question is - why it works like this (feature/bug)?
P.S. My env is Node 4.1
P.P.S. My output:
Status #1: Promise { <pending> }
Resolve 1
Value after: 1
Status #2: Promise { 1 }
Resolve 2
Status #3: Promise { 1 }
It is not safe to resolve/reject promise multiple times. It is basically a bug, that is hard to catch, becasue it can be not always reproducible.
')); }); An important point to note: A Promise executor should call only one resolve or one reject . Once one state is changed (pending => fulfilled or pending => rejected), that's all.
A promise that is either resolved or rejected is called “settled”, as opposed to an initially “pending” promise. There can be only a single result or an error. The executor should call only one resolve or one reject . Any state change is final.
So failing to resolve or reject a promise just fails to ever change the state from "pending" to anything else. This doesn't cause any fundamental problem in Javascript because a promise is just a regular Javascript object.
Well, I want to talk about the why. Promises are proxies for single values so running handlers a second time or changing the value doesn't make sense. You can't change the number 5 to be the number 3 for instance.
Let's talk about what alternatives we have for resolve
being called a second time. Let's say we didn't want to allow it - how would we signal that?
Normally, we'd throw
- the problem is - it would be caught nowhere since throw
s in the promise constructor get converted to rejections. .catch
handlers would not run because the promise already resolved.
So we can't really throw as that'd mean an exception you can't handle (a very bad place to be). We can't run handlers twice (that would break the model). So our only choice left is to allow it.
As per the ECMAScript 2015 Specification, sections Promise Reject Functions and Promise Resolve Functions say that,
- If alreadyResolved.[[value]] is true, return undefined.
So, if the current promise object is already resolved, then neither resolve, nor reject do anything to the Promise object. It actually means that, only the first resolve/reject matter.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With