简体   繁体   中英

Handling expected vs operational errors with A+ Promises

I've been using bluebird promises for a while now and one thing I really like about them is their implementation of a targetted 'catch' as well as the .error short hand for explicitly catching OperationalErrors.

This allows me to do things like:

var p = new Promise(/*stuff*/);
p.then(function(){ /* good */ })
.error(function(){ /* only handle expected operational cases */ });
.catch(function(){ /* if needed, handle unexpected errors, usually just crash */});

However in the promise spec, there is no ".error", the closest thing would look more like:

var p = new Promise(/*stuff*/);
p.then(function(){ /* good */ })
.catch(function(e){
        if (e instanceof ThingIExpect){
            //do something
        }else{
            throw e; //die
        }
});

But one of the benefits of the .error syntax is that by NOT using catch, code like this will just crash, which imho is what it should do:

"use strict";
var p = new Promise(function(f,r){
    a = 10; //Reference Error
    f(true);
});


p.then(function(val){
    console.log(val); //never gets hit - ReferenceError
}).error(function(e){
    console.log(e); //never gets hit - ReferenceError
});

Here my reference error just crashes. Using bluebird I never have to worry about a junior developer doing this as long as I lint, or code review for .catch being used only when needed.

"use strict";
var p = new Promise(function(f,r){
    a = 10; //Reference Error
    f(true);
});


p.then(function(val){
    console.log(val); //never gets hit - ReferenceError
}).catch(function(e){
   //attempt to handle ReferenceError instead of just crashing.
});

There is also no concept of OperationalError, a rejection is just type Error. So it is difficult to check explicitly for rejections vs other possible errors unless you always reject on your own custom types.

So with all of that said, finally the question:

What is the best way to approach operational vs expected errors when writing an application using native Promises or something that implement the A+ spec to the letter?

Rather than rejecting with a custom error, consider moving "expected failures" into the success case. In other words, instead of:

var p = new promise(function (f, r) {
    var result = getResult();
    if (result > 5) { f(result); }
    else { r(new Error("result was too small")) }
});

Try:

var p = new promise(function (f, r) {
    var result = getResult();
    if (result > 5) { 
        f({success: true, result: result}); 
    }
    else { 
        f({success: false, reason: "result was too small"}); 
    }
});

Now you know that the error-case handler will only be called for unexpected failures, which is what you're interested in.

Another upside is that you're now modelling operational errors explicitely, and who ever's writing the fulfillment handler will be encouraged to think about handling the success: false case.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM