Idiomatically handling pre-conditions with ES6 Pro

2019-01-20 11:41发布

问题:

I am new to ES6 Promises and have been doing research. I have some code executing in NodeJS that does some async work, but I have a few pre-conditions that must be checked first. I'm seeking the idiomatic best-practice for dealing with this (if such a thing exists) along with some reasoning. I hope to gain an understanding, as I already have working code.

Consider the following fictional snippet:

function doStuff(data, cb) {
     if (!data) {
         return cb(new Error("Don't be an idiot"));
     }

     externalLibrary.doSomethingCallbackAsync(data, cb);
}

Were I to translate this into promise-land, I see two options.


Option 1, I can include the pre-condition in the promise.

function doStuff(data){
    return new Promise((resolve, reject) => {
        if (!data) {
            return reject(new Error("Don't be an idiot"));
        }

        externalLibrary.doSomethingCallbackAsync(data, function(err, newData) {
            if (err) {
                return reject(err);
            }
            return resolve(newData);
        });
    });
}

Option 2, I can run the pre-condition prior to the promise. I'm not certain I understand the intent of Promise.reject(), but it seems to fit the bill here by allowing me to return an immediately rejected promise.

function doStuff(data){
    if (!data) {
        return Promise.reject(new Error("Don't be an idiot"));
    }

    return new Promise((resolve, reject) => {
        externalLibrary.doSomethingCallbackAsync(data, function(err, newData) {
            if (err) {
                return reject(err);
            }
            return resolve(newData);
        });
    });
}

I prefer Option 2 for readability reasons, but I don't fully understand Promise.reject() and I am concerned that Option 2 is misusing it. Just to reiterate, I am looking for a best-practice solution.

回答1:

I'm not certain I understand the intent of Promise.reject(), but it seems to fit the bill here

You've understood it correctly. It's explicitly made for use cases such as this. Go for it, it is the best practice.

The advantage of Option 2 is that it works much cleaner with APIs that already do return promises (think return externalLibrary.doSomethingAsync(data)), and has less chance to fall for the Promise constructor antipattern.