1

I am trying to convert my old callback style functions to async await. However I can't understand how can I catch unhandled exceptions.

For example let's say I have a function

  apiCall(input, function(error, result) {
    if (error) {
      console.log(error);
    } else {
      console.log(result);
    }
  });

I converted to Promise

function test1(input) {
  return new Promise(function(resolve, reject) {
    apiCall(input, function(err, result) {
      if (err) {
        reject(err);
      } else {
        resolve(result);
      }
    });
  });
}

Then I call it

test1(4)
  .then(function(result) {
    console.log('Result: ' + result);
  })
  .catch(function(errorr) {
    console.log('My Error: ' + errorr);
  });

Even though I try to return error, sometimes this function crashes. Let's say disk error, JSON parsing error etc. Some error that I didn't handle. I can only catch those errors with

process.on('uncaughtException', function(error) {
  console.log('uncaughtException' + error);
});

Is there a way for me to catch all kinds of error with async await?

EDIT: Here is the full github repo for you to try

https://github.com/tosbaha/promise

Run node testme.js and see that it crashes and exception handler doesn't run.

The file that may crash is this Any function may crash but I can't foresee every kind of error. That is why I am looking for a solution to catch an error inside this file.

If you run the code in my repo with node testme.js you will get the following error

        results[trackingId] = trackingArray.doesntExist.Something;
                                                        ^
TypeError: Cannot read property 'Something' of undefined

As you see that catch handler doesn't catch the error.

Meanteacher
  • 2,031
  • 3
  • 17
  • 48
  • It could be that only `reject` or `resolve` is defined at any one time. Instead of using `if..else` use `reject(err || ''); resolve(result);` – Airerr Dec 10 '17 at 19:04
  • If apiCall returns error, this works. If apiCall returns result this works again. However if apiCall crashes due to lets say `Cannot read property 'Something' of undefined` which I didn't handle in apiCall, then I can't catch this error besides `uncaughtException` handler – Meanteacher Dec 10 '17 at 19:07
  • 1
    Consider using `try...catch` in those cases. – Airerr Dec 10 '17 at 19:09
  • what version of node are you using? In the chrome browser v8 native promises do not throw uncaught errors: `new Promise( ()=>{throw "no uncaught error"} ) .catch(x=>console.log("no problem"))` Are you importing a badly written promise polyfill – HMR Dec 10 '17 at 19:14
  • I am using NodeJS v8.7.0 I can't catch all errors if I don't use uncaughtException – Meanteacher Dec 10 '17 at 19:17
  • What native API are you using that it won't work? The code I pasted works in 8.9.1 and logs "no problem". Maybe the API crashes node in a way that can't be caught? – HMR Dec 10 '17 at 19:20
  • I will put a full example on github sir. I am sorry for the inconvenience. – Meanteacher Dec 10 '17 at 19:23
  • No problem, I remember some API causing process to crash that can't be caught maybe it was [pipe and stream](https://stackoverflow.com/questions/21771220/error-handling-with-node-js-streams) but I'm not sure – HMR Dec 10 '17 at 19:27
  • 1
    What does the stack trace says? Are you sure that is your code failing? Maybe some other part fails and `process.on()` handles it before process is dying? – andy Dec 10 '17 at 19:31
  • @HMR I added a github repo. – Meanteacher Dec 10 '17 at 19:33
  • 2
    You should link to the actual file and the line of code, for example [this](https://github.com/tosbaha/promise/blob/master/lib/abstract_courier.js#L8) – HMR Dec 10 '17 at 19:42
  • If the error really is `Cannot read property 'Something' of undefined` theres a really huge bug in your code. Dont try to silence the error, rather try to reolve it! – Jonas Wilms Dec 10 '17 at 19:43
  • Sir, I just put that error to show that if an error occurs there, I can't catch it. I am looking for a way to catch those kind of errors. – Meanteacher Dec 10 '17 at 19:46
  • Code in that repo doesn't crash, the last line of output is: `My Error: Error: Unknown Error` Could you update the answer with the full stack of the error? – HMR Dec 11 '17 at 04:30
  • Running node testme.js with NodeJS v8.7.0 crashes with following error results[trackingId] = trackingArray.doesntExist.Something; ^TypeError: Cannot read property 'Something' of undefined – Meanteacher Dec 11 '17 at 09:09

1 Answers1

0

If apiCall can crash without calling the callback (with an error), I assume it throws some error that can be handled outside it with a try... catch block (although I'm not sure, because I don't know the internal code of apiCall).

You can try the following:

function test1(input) {
  return new Promise(function(resolve, reject) {
      try {
        apiCall(input, function(err, result) {
          if (err) {
            reject(err);
          } else {
            resolve(result);
          }
        });
      } catch (e) {
        // reject the errors not passed to the callback
        reject(e);
      }
  });
}
Lucas Basquerotto
  • 7,260
  • 2
  • 47
  • 61
  • I have found out that there is no easy way to catch exceptions in async functions. Only way to catch those kind of exceptions is using `domain`. I searched high and low and even though domain is going to be deprecated, it is the only way. – Meanteacher Apr 09 '18 at 15:33