Handling Js promise rejection
Asked Answered
L

5

5

How do you handle an error (eg. "new error" below) that is outside of the promise?

function testError() {
    throw new Error("new error") // how to handle this?
    var p123 = new Promise(function(resolve, reject) {
         resolve(123)
    });
    return p123
};

testError().catch(err => {
        return err;  // code doesn't come here
    })
    .then(ok => {
        console.log(ok)
    });
Lupercalia answered 14/4, 2017 at 7:15 Comment(3)
Use try/catchMarlysmarmaduke
You'll have to throw the error inside the promise function for the .catch() to work.Disaccord
See How can I catch an asynchronous error using JS promises?Jilleen
M
6

If you're not sure whether a function will throw (or return a value) synchronously, you can call it using .then(). This will wrap it so that the result will be handled consistently no matter how it is produced:

function testError() {
  throw new Error("new error") // how to handle this?
  var p123 = new Promise(function(resolve, reject) {
    resolve(123)
  });
  return p123
};

Promise.resolve()
  .then(testError)
  .catch(err => {
    console.error(err);
    return err; 
  })
  .then(ok => {
    console.log(ok.message)
  });
Miguelmiguela answered 14/4, 2017 at 7:20 Comment(1)
Note that, since ES2018, you can use .finally() instead of the second .then() call, which does the same thing but is clearer as to the intention (It will always be called, even if the promise error'd out).Peace
P
4

Since the error doesn't involve the async code, a regular try-catch should do fine here:

try {
  testError().catch(err => {
    return err;  // code doesn't come here
  })
  .then(ok => {
     console.log(ok)
  });
}
catch(e) {
   // 
}

Note that when the async-await pattern finally becomes the native way of resolving promises, the try-catch will also become the native way of handling errors:

try {
    var ok = await testError();
    console.log(ok)
}
catch(e) {
    console.log('e:' +e);
}

As one can easily verify, this one correctly handles both the sync and the async error and is much cleaner than then-catch.

Pudendum answered 14/4, 2017 at 7:21 Comment(3)
This will work, but it makes the logic flow very messy and destroys the uniformity that promises provide.Miguelmiguela
@JLRishe: addressed this in my answer - the try-catch provides the ultimate uniformity.Pudendum
It does if async/await are available, but not when they aren't available.Miguelmiguela
P
1

If you can, rewrite your testError function like so

function testError () {
  return new Promise(function (resolve, reject) {
     throw new Error('new error')
     resolve(123)
  })
}

testError().then(ok => console.log(ok),
                 err => console.error(err.message))
  1. Run it once to see it throw the error in console.error
  2. Comment out the throw line to see the promise resolve successfully
Pelham answered 14/4, 2017 at 8:32 Comment(0)
C
0

Since the error is thrown outside of the promises, you cannot catch it using a promise catch statement.

You can use a try/catch to catch the error instead.

function testError() {
    throw new Error("new error") // how to handle this?
    var p123 = new Promise(function(resolve, reject) {
         resolve(123)
    });
    return p123
};

try {
  testError().then(ok => {
    console.log(ok)
  });
} catch (err) {
  console.log(err.message);
}
Charlet answered 14/4, 2017 at 7:22 Comment(0)
W
0

You rewrite it, because making a caller check for both exceptions and rejections is an anti-pattern:

function testError() {
  return Promise.resolve().then(() => {
    throw new Error("new error"); // rejects returned promise
    return new Promise(function(resolve) {
      resolve(123);
    });
  });
}

testError().catch(err => console.log("Caught " + err));

This is implicit with async functions; they always return a promise:

async function testError() {
  throw new Error("new error"); // rejects implicit promise
  return await new Promise(function(resolve) {
    resolve(123);
  });
}

testError().catch(err => console.log("Caught " + err));
Woodall answered 15/4, 2017 at 2:54 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.