Dont understand javascript promise antipattern, returning promise from callback

后端 未结 1 1661
北海茫月
北海茫月 2021-01-07 15:35

Could someone explain to me why returning promises in promises callbacks is considered antipattern? Apparently it breaks exception bubbling but obviously my understanding of

相关标签:
1条回答
  • 2021-01-07 15:50

    "You must also never mix callbacks with promises because then you lose exception bubbling (the point of promises) and make your code super verbose."

    What Petka means here, is that you should not use callback based methods in your user code together with Promises because this will make your code very verbose, as illustrated by your example.

    It's verbose because you have to manually resolve or reject a new Promise based on the callback every time you call the function.

    setTimeout Example:
    You have to manually call the resolver when the timeout completes. Now setTimeout is a bit of a poor example as it does not have a possibility to reject it's operation.

    return new Promise(function (resolve, reject) {
            console.log("b");
            setTimeout(function () {
                resolve("timeout2");
            }, 2000);
        })
    

    Better example
    Say you want to call fs.readFile like so:

    return new Promise(function (resolve, reject) {
        fs.readFile('foo.txt', function (err, res) {
            if (err){
                reject(err);
                return;
            } else {
                resolve(res);
            }
        });
    })
    

    Here you have to ether resolve or reject because you are mixing promises with callbacks, this will make your code very brittle and confusing.

    Solution:

    Instead of creating new Promises all over the place whenever you need to call a method that only supports callbacks, wrap that callback based method once and use that everywhere.

    var readFileAsync = new Promise(function (resolve, reject) {
        fs.readFile('foo.txt', function (err, res) {
            if (err){
                reject(err);
                return;
            } else {
                resolve(res);
            }
        });
    });
    

    Bonus:

    You don't even need to do this wrapping your self, bluebird has got you covered. Checkout promisification right here:

    https://github.com/petkaantonov/bluebird/blob/master/API.md#promisification

    This whole explanation is sort of beside the fact that it is completely valid to return a Promise inside a promise's onFulfilled method. This is part of the Promise/A+ spec, see the The Promise Resolution Procedure -> 2.3.2 If x is a promise, adopt its state [[3.4](#notes)]:

    I assume your confusion originates from the fact that Petka is telling you not to create and return new promises in your example. But this has nothing to do with the fact that you are returning Promises, but rather with the fact that you shouldn't be creating promises at that place, as stated here above.

    Use a wrapped version, and then you are good to return/chain them wherever you want.

    0 讨论(0)
提交回复
热议问题