I think I have finally managed to bend my mind around javascript/ES6 Promises, for the most part. It wasn't easy! But there's something that's baffling me about the design.
Why does the Promise constructor take a callback? Given that the callback is called immediately, couldn't the caller just execute that code instead, thereby avoiding one unnecessary level of mind-bending "don't call me, I'll call you"?
Here's what I think of as the prototypical example of Promise usage, copied from Jake Archibald's Javascript Promises tutorial http://www.html5rocks.com/en/tutorials/es6/promises/#toc-promisifying-xmlhttprequest , with comments stripped.
It's a Promise-based wrapper for an XMLHttpRequest GET request:
function get(url) {
return new Promise(function(resolve, reject) {
var req = new XMLHttpRequest();
req.open('GET', url);
req.onload = function() {
if (req.status == 200) {
resolve(req.response);
}
else {
reject(Error(req.statusText));
}
};
req.onerror = function() {
reject(Error("Network Error"));
};
req.send();
});
}
For me, the above code would be much easier to understand if it were rewritten as follows, using a very slightly different kind of promise that I'm imagining, having a no-arg constructor and resolve/reject methods:
function get(url) {
var promise = new MyEasierToUnderstandPromise();
var req = new XMLHttpRequest();
req.open('GET', url);
req.onload = function() {
if (req.status == 200) {
promise.resolve(req.response);
}
else {
promise.reject(Error(req.statusText));
}
};
req.onerror = function() {
promise.reject(Error("Network Error"));
};
req.send();
return promise;
}
MyEasierToUnderstandPromise is not too hard to implement in terms of Promise. At first I tried making it an actual subclass of Promise, but for some reason I couldn't get that to work; so instead I implemented it as a simple factory function, which returns a plain old Promise object with a couple of extra functions attached that behave like member functions:
function NewMyEasierToUnderstandPromise() {
var resolveVar;
var rejectVar;
var promise = new Promise(function(resolveParam, rejectParam) {
resolveVar = resolveParam;
rejectVar = rejectParam;
});
promise.resolve = resolveVar;
promise.reject = rejectVar;
return promise;
};
So, why isn't Promise designed like this? I think if it was, it would have helped me to understand Promises a lot quicker-- I bet it would have cut my learning time in half.
I know a lot of smart people had a hand in making the Promise API, and everyone seems to be generally happy and proud of it, so I'm wondering what they were thinking.
Your version is not exception-safe, whereas Promises/A+ are safe since they are caught by the Promise
constructor.
Promises are intended to be used as values. The ES constructor approach encapsulates the creation of the Promise, which can then be passed around like a value. When that value is passed around, the consumer of that value has no need for resolve
and reject
and so those functions should not be part of the public API.
(and all that stuff about exception handling and chaining)
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