Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JavaScript Callback Error Handling

It's common to validate arguments and return error in functions.

However, in JavaScript callback function, such as:

function myFunction(num, callback) {
  if (typeof num !== 'number') return callback(new Error('invalid num'))
  // do something else asynchronously and callback(null, result)
}

I wrote a lot of functions like this, but I wonder if there's something potentially harmful. Because in most cases, the caller assumes this is an asynchronous function and the callback will execute after the code right after the function call. But if some arguments are invalid, the function will immediately call the callback. So the caller must be careful dealing with the situation, that is, an unexpected execution sequence.

I want to hear some advice on this issue. Should I carefully assume that all asynchronous callbacks may be executed immediately? Or I should use something like setTimeout(..., 0) to convert synchronous thing to asynchronous one. Or there's a better solution I don't know. Thanks.

like image 296
matianfu Avatar asked Aug 09 '16 14:08

matianfu


People also ask

How do you handle errors in callback?

If an error-handling callback function has been specified in the application and if the value of the error parameter is NULL, the error parameter is passed to the specified callback function, and the operation that encountered the error condition returns a value of DW_DLV_ERROR.

How do you handle errors in JavaScript?

JavaScript provides error-handling mechanism to catch runtime errors using try-catch-finally block, similar to other languages like Java or C#. try: wrap suspicious code that may throw an error in try block. catch: write code to do something in catch block when an error occurs.

Should you throw errors in JS?

It's best to avoid throwing errors from inside a Promise, because they may not always be caught, depending on how the code that called them is structured. However it's good practice to return an error when rejecting a Promise, and you can return Error custom types just like any other Error.


1 Answers

The caller of your asynchronous function should know what's going to be the result of invoking the function. There is a standard for what an asynchronous function should return, Promises.

If your function returns a Promise, anybody can easily understand what's going on in that function. Promises have the reject callback, but we could argue if the validation of the parameters should be handled by rejecting the promise or if an exception should be thrown straight forward. Either way, if the caller handles exceptions properly using the catch method, both directly thrown exceptions and rejects will be captured in the same manner.

function throwingFunction(num) {
  return new Promise(function (resolve, reject) {

    if (typeof num !== 'number') throw new Error('invalid num');
    // do something else asynchronously and callback(null, result)
  };
}

function rejectingFunction(num) {
  return new Promise(function (resolve, reject) {

    if (typeof num !== 'number') reject(new Error('invalid num'));
    // do something else asynchronously and callback(null, result)
  };
}

// Instead of passing the callback, create the promise and provide your callback to the `then` method.

var resultThrowing = throwingFunction(num)
    .then(function (result) { console.log(result); })
    .catch(function (error) { console.log(error); });

var resultRejecting = rejectingFunction(num)
    .then(function (result) { console.log(result); })
    .catch(function (error) { console.log(error); });

Both patterns will result in the error being catched and logged.

If you use promises, the caller of your asynchronous function will not have to worry about your implementation inside the function, and you can either throw the error straight foward or reject the promise as you please.

like image 162
Marco Scabbiolo Avatar answered Sep 20 '22 06:09

Marco Scabbiolo