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.