What is faster: try catch vs Promise

29,036

Solution 1

You should use Promises only for asynchronous functions and nothing else. Do not abuse them as an error monad, that would be a waste of resources and their inherent asynchrony will make every­thing more cumbersome.

When you have synchronous code, use try/catch for exception handling.

/* Wrong */
return new Promise(function(resolve, reject) {
    resolve(x / y);
}).catch(err => NaN)

/* Right */
try {
    return x / y;
} catch(e) {
    return NaN;
}

If you already have promise code, you can avoid that in certain situations: when you want the exception to reject the promise. In those cases you should just let the builtin error handling of your promises do its job, and not complicate everything by an additional but pointless try/catch layer:

/* Wrong */
new Promise(function(resolve, reject) {
    try { // when used synchronous in the executor callback
        …
        resolve(somethingSynchronous());
    } catch (e) {
        reject(e);
    }
});

/* Right */
new Promise(function(resolve, reject) {
    …
    resolve(somethingExceptionally());
});
/* Wrong */
….then(function(res) {
    try {
        …
        return somethingExceptionally();
    } catch(e) {
        return Promise.reject(e);
    }
}).…

/* Right */
….then(function(res) {
    …
    return somethingExceptionally();
}).…

Solution 2

try/catch idiom works very well when you have fully synchronous code, but asynchronous operations render it useless, no errors will be caught. i.e., the function will begin its course while the outer stack runs through and gets to the last line without any errors. If an error occurs at some point in the future inside asynchronous function – nothing will be caught.

When we use Promises, “we’ve lost our error handling”, you might say. That’s right, we don’t need to do anything special here to propagate error because we return a promise and there’s built in support for error flow.

Share:
29,036
Maksim Nesterenko
Author by

Maksim Nesterenko

Updated on October 25, 2021

Comments

  • Maksim Nesterenko
    Maksim Nesterenko over 2 years

    I heard such an opinion that you should avoid usage of try/catch at all because it takes many resources. So could the promise error handling to be faster? Or it does not matter at all?

    function f(somethingDangerous) {
      return new Promise((resolve, reject) => {
        // try {
        //   somethingDangerous();
        //   resolve();
        // } catch (err) {
        //   reject(err);
        // }
    
        // VS
    
        somethingDangerous();
        resolve();
      }).catch((err) => {
        console.error('Catched: ' + err);
      });
    }
    
    f(() => {throw 'DANGEROUS THING';});
    

    UPD: I know that try/catch won't work with async code inside. I'm just wondering if there any reasons to avoiding of try/catch because of performance issues? And is there any difference between the two approaches above?

    UPD2: Tried to race my horses :) https://jsperf.com/try-catch-vs-promise

  • Mulan
    Mulan about 7 years
    I added an example of Promise abuse where try/catch should be used instead. I hope it serves your answer well.
  • Bergi
    Bergi about 7 years
    @naomik Thanks, however division throwing an exception is pretty rare :-) (Yes, the ToNumber cast could do it)
  • SET001
    SET001 over 6 years
    This is not true, since we now have async/await. With it's usage we can now consider all code to be sync.
  • velop
    velop almost 5 years
    And I already thought that everything has to be put into a monad ^^,
  • Matheus Ribeiro
    Matheus Ribeiro about 3 years
    Not really, as you can await for a asynchronous call inside try {} block
  • Mattias
    Mattias about 3 years
    How about try { const c = await someFunction(); doSomething(c) } catch (e) { console.error(e) } finally { doSomethingElse() }. This could be written as someFunction().then(c => doSomething(c)).catch(e => console.error(e)).finally(() => doSomethingElse()), but what are the performance differences? Why should the first way not be used, or am I getting the answer wrong?
  • Bergi
    Bergi about 3 years
    @Mattias No, my answer only says that you shouldn't reject promises from error handlers yourself. Both versions of your code are fine, and the first probably even is better optimised by engines.
  • Mattias
    Mattias about 3 years
    @Bergi I though I was missing something in your answer, I even tried to write some loops to get a better feel for one way or the other, but since performance measurement code is quite tricky, and my results went like 100x faster with the try/catch block than the .then().catch() statement, I just had to see what I misunderstood.