3

From node doc:

A handful of typically asynchronous methods in the Node.js API may still use the throw mechanism to raise exceptions that must be handled using try / catch. There is no comprehensive list of such methods; please refer to the documentation of each method to determine the appropriate error handling mechanism required.

Can someone bring example of such function which is async and still throws? How and when do you catch the exception then?

More particularly. Do they refer to such function:

try
{

   obj.someAsync("param", function(data){
                    console.log(data);
                 });
}catch(e)
{

}

Now normally I know above doesn't make sense -because when the callback executes, try block could have been already exited.

  • But what kind of example does the excerpt from documentation refer to? If async method throws as they say it, where, when and how should I handle it? (or maybe if you show such function can you show where in its doc it says how to handle it as mentioned on the quote?)
Giorgi Moniava
  • 27,046
  • 9
  • 53
  • 90
  • can you give an example of such function, I could try it out.. – Abhinav Gauniyal Feb 13 '17 at 11:42
  • @AbhinavGauniyal Well if you look carefully at the question, I am looking for that function (or hypothetical one) and the ways you would handle it myself – Giorgi Moniava Feb 13 '17 at 11:43
  • oh, not sure how I skipped over that. Usually I've seen errors being passed as `err` parameter from parent async function to the callback, so I'm curious as well. – Abhinav Gauniyal Feb 13 '17 at 11:45
  • @AbhinavGauniyal Yep, you can check the doc well, that `err` case is addressed separately, and this one separately. – Giorgi Moniava Feb 13 '17 at 11:46
  • I think it can for example happen if you give invalid arguments to the function which starts the async operation (`someAsync` here). Then it doesn't make sense for the operation to start at all and it's better to throw an exception immediately than to execute the callback with an error. – Matthias247 Feb 13 '17 at 11:52
  • @Matthias247 Where do you catch such exception than? – Giorgi Moniava Feb 13 '17 at 11:57
  • 2
    @GiorgiMoniava if it helps - https://github.com/nodejs/docs/issues/124 – Abhinav Gauniyal Feb 13 '17 at 11:58
  • @GiorgiMoniava A synchronous exception can be catched in a try/catch block, like you've shown. An async exception will be delivered as an error callback parameter, just like the default node workflow is. – Matthias247 Feb 13 '17 at 14:26

2 Answers2

3

The async methods like the one from your example usually throw for programmer errors like bad parameters and they call the callback with error for operational errors.

But there are also async functions in ES2017 (declared with async function) and those signal errors by rejecting the promise that they return - which turn into a thrown exception when you use them with await keyword.

Examples:

function x(arg, cb) {
    if (!arg) throw new Error('Programmer error: bad arguments');
    setTimeout(() => {
        cb(new Error('Operational error: something bad happened'));
    }, 2000);
}

Now when you use it you usually don't want to handle programmer errors - you want to fix them. So you don't do this:

try {
    x();
} catch (err) {
    // Why should I handle the case of bad invocation
    // instead of fixing it?
}

And the operational errors you handle like this:

x(function (err) {
    if (err) {
        // handle error
    } else {
        // success
    }
});

Now, if you have a function that doesn't take a callback but returns a promise:

function y() {
    return new Promise((res, rej) => setTimeout(() => rej('error'), 2000));
}

Then you handle the error like this:

y().catch(error => {
    // handle error
});

or, while using await:

try {
    await y();
} catch (err) {
    // handle error
}

For more info on the difference between operational errors and programmer errors see:

For more info on the promises and async/await see the links in this answer.

rsp
  • 107,747
  • 29
  • 201
  • 177
  • An example of this would be if you were to call `dns.lookup({})`. That would throw. – Evan Lucas Feb 13 '17 at 12:01
  • I'm trying to understand this part of documentation - `that must be handled using try / catch`, if you ignore this and still handle it by usual `if (err) { }` syntax, then either documentation states it wrong or you are not handling them correctly. **Note** that documentation does have another section of `if (err) { }` way of handling errors which signifies that those are different than `try/catch` point which adds up to the confusion. – Abhinav Gauniyal Feb 13 '17 at 13:24
  • @rsp: Did I understand correctly if I need to use your *first* function `x` from your example, I would both need to enclose it in try/catch and check err inside callback? – Giorgi Moniava Feb 13 '17 at 14:01
  • 1
    @GiorgiMoniava Actually it depends. To use my first function `x()` you need to do it both only if you need to handle the programmer error of invoking the `x()` function with wrong arguments, but if you prefer this error to stop your program so that you can notice it and fix then you don't want try/catch there and you should only check for `err` in the callback, because this is an operational error that can happen even if the program is correct (like lost connection to the database or something like that) and there is nothing to fix. See articles about handling errors in my answer for rationale – rsp Feb 14 '17 at 10:38
-1

afaik there are three ways a async function could "throw"; and how to catch each of these:

  • as any other function (aka. someone messed up): I'd not catch these cases because they should not be in my code, and catching such errors makes it harder to find and fix em.

function foo(){
//someone messed up, better fixing than catching this
return new Prooooooooooomise((resolve) => 42);
}

try {
foo();
}catch(err){
console.error(err);
}
  • Promises:

function foo(){ return Promise.resolve('bar') }

foo().then(value => value =========> 'error')
.catch(err => {
 console.error(err);
 return "fixedValue";
});
  • And Nodes callback syntax/pattern:

function foo(value, callback){
setTimeout(function(){
 if(Math.random() < .5){
  callback("I don't like to", undefined);
 }else{
  callback(null, value * 2);
 }
}, 500);
}

foo(21, function(err, data){
if(err){
 //no try..catch at all
 console.error(err);
}else{
 //do whatever with data
}
})

These are the most common async errors you'll come along; well, the first one is just a plain bug in an async mothod.

Thomas
  • 11,958
  • 1
  • 14
  • 23