Domanda

This is not a "how does it work" but "why is it this way - what am I missing" question:

I think I've gotten the hang of the javascript Promise construct - very clever, simple and nice. I love it. But I do wonder - and I'm sure someone can give me a good answer - why is the Promise constructor different from the .then() method?

some_promise.then(
    function(){
        if (some_condition) {
            return 'It works!';
        } else {
            throw Error('Noooooo!');
        }
).then(
    function(message){
        console.log('I was told: '+message);
    }
).catch(
    function(err) {
        console.log('Dang, it broke!');
    }
)

works like a charm, but in order to get the original promise to work, you HAVE to do:

var some_promise = new Promise(function(resolve, reject){
    if (some_condition) {
        resolve('It works!');
    } else {
        reject(Error('Noooooo!'));
    }
});

I had a hard time wrapping my head around promises at the beginning. The concept was simple enough, but the examples (like above) confused me greatly, and I figured out it was this difference that got me - it seems inconsistent to me. Is there any reason why the standard isn't more along the lines of:

//Modification to the standard
Promise.to = function(action){
    return new Promise(function(resolve, reject){
        resolve(true);
    }).then(action);
}

//Would result in a new Promise being constructed / used like this:
var some_promise = Promise.to(function(){
    if (some_condition) {
        return 'It works!';
    } else {
        throw Error('Noooooo!');
    }
}).then(
    function(message){
        console.log('I was told: '+message);
    }
).catch(
    function(err) {
        console.log('Dang, it broke!');
    }
)

I don't do this, because I think it's a bad idea to modify the base "classes" in javascript, but the example above seems to be working.

What would be lost if the standard worked this way? I guess something, but what am I not getting? It seems to be simpler to grasp, when getting aquainted with this concept and it's less verbose.

È stato utile?

Soluzione

The entire purpose of the resolve and reject callbacks is that they can be called at any time, even after the construction function has finished. This makes is useful for asynchronous operations which can be started at construction but not completed before the constructor completes. As your examples only deal with the synchronous case, this advantage is lost. (...actually, it's more than an advantage... it's the entire reason for the existence of Promises).

You can also return promises from your continuations, such that the subsequent continuation (or .then clause) will only run when the previously returned Promise has completed. All good, but you'd be left with the problem of how to make an async promise in the first place without the original interface.

Altri suggerimenti

The point of the promise constructor is indeed to allow asynchronous promise completion.

However, if you are not doing that, then what you describe is present in many promise libraries. For example, in bluebird it is Promise.try:

var some_promise = Promise.try(function(){
    if (some_condition) {
        return 'It works!';
    } else {
        throw Error('Noooooo!');
    }
}).then(
    function(message){
        console.log('I was told: '+message);
    }
).catch(
    function(err) {
        console.log('Dang, it broke!');
    }
)

Also, if you want to use then, you can just start off with an already resolved promise by using Promise.resolve:

Promise.resolve(undefined).then(
    function(){
        if (some_condition) {
            return 'It works!';
        } else {
            throw Error('Noooooo!');
        }
).then(
    function(message){
        console.log('I was told: '+message);
    }
).catch(
    function(err) {
        console.log('Dang, it broke!');
    }
)

But, to reiterate, this is only relevant if you do not actually need the asynchronous nature of the promise constructor - like in the examples you gave above. It is not rationale for making the Promise constructor any different from what it is, because it has a well defined purpose and need.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top