Generally, there are two kinds of error handling among all programming langauges:
- Create a scope, anything does wrong during execution will ternimate the scope and jump to the error handling part, e.g.
try-catch
,superviser with actors
. This style is usually preferrable with scripting. - Error is explicitly passed to caller, and encourage explicit handling of every single error, e.g. Go, C, node.js with callbacks. And this is very useful in critical systems as every error matters.
Async/await changed the error handling style of Node.js from explicit to scoped. In many cases this is enjoyable, but once developer really needs to take care of every error, it becomes annoying, e.g.:
async fucntion(){
let result1, result2 ...
try{ result = await doSomething1(); } catch(e){ //handle it, change flow, or continue }
try{ result2 = await doSomething2(); } catch(e){ //handle it, change flow, or continue based on results1 }
....
...
}
2016 I forked co.js
as co-nothrow
and make it possible to provide the explicit handling option back to Node with generator function, and now it surprisingly works with async/await as well.
const co = require("co-nothrow");
async function doSomething() {
return await new Promise((res, rej) => {
setTimeout(function () {
res("hello");
}, 1000);
})
}
async function doSomethingWrong() {
throw "something wrong"
}
co(function* () {
let [err, res] = yield doSomething();
if (err) {
return console.error(err);
}
console.log("do something: ", res);
[err, res] = yield doSomethingWrong();
if (err) {
return console.error(err);
}
console.log(res);
})
So you can pick whatever style you like based on you need for your logics.