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)
    });
Mr. ProxY
  • 17
  • 1
  • 4
Stanley
  • 2,798
  • 5
  • 22
  • 44

5 Answers5

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)
  });
JLRishe
  • 99,490
  • 19
  • 131
  • 169
  • 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). – batjko Mar 20 '18 at 08:32
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.

Wiktor Zychla
  • 47,367
  • 6
  • 74
  • 106
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
Mulan
  • 129,518
  • 31
  • 228
  • 259
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);
}
clinton3141
  • 4,751
  • 3
  • 33
  • 46
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));
jib
  • 40,579
  • 17
  • 100
  • 158