04.ii Promise.catch()

Метод promise.catch(onRejected) возвращает новый Promise реагирующий только на переход в rejected состояние. Если catch обработчик отработал, то Promise считается возвращенным в fulfilled состояние.

const promise = Promise.resolve("Success.");
promise
  .then(value => {
    console.log(value); // "Success!"
    return Promise.reject("Failure.");
  })
  .catch(e => {
    console.log(e); // Failure
  })
  .then(
    () => {
      console.log("after a catch the chain is restored");
    },
    () => {
      console.log("Not fired due to the catch");
    }
  );
// Success.
// Failure.
// after a catch the chain is restored

Errors thrown inside asynchronous functions will act like uncaught errors:

const promise = new Promise((resolve, reject) => {
  setTimeout(() => throw "Uncaught Exception!", 1000);
});

promise.catch(e => {
  console.log(e); // This is never called
});

Errors thrown after resolve is called will be silenced:

const promise = new Promise((resolve, reject) => {
  resolve();
  throw "Silenced Exception!";
});

promise.catch(e => {
  console.log(e); // This is never called
});

Catch errors on normal flow

Если есть Promise и на нем установлены две реакции на fulfilled и rejected случаи, то проблема в том, что исключение произошедшее в fulfilled случае не будет перехвачено в rejected обработчике:

somethingAsync.then(
  () => {
    return somethingElseAsync();
  },
  err => {
    handleMyError(err);
  }
);

Решение:

somethingAsync
  .then(() => {
    return somethingElseAsync();
  })
  .catch(err => {
    handleMyError(err);
  });

Handling exceptions in Promise-based functions

If exceptions are thrown inside the callbacks of then() and catch() then that’s not a problem, because these two methods convert them to rejections.

However, things are different if you start your async function by doing something synchronous:

function asyncFunc() {
    doSomethingSync(); // (A)
    return doSomethingAsync().then(result => {
        ···
    });
}

If an exception is thrown in line A then the whole function throws an exception. There are two solutions to this problem.

  • returning a rejected Promise

  • executing the sync code inside a callback

//  Solution 1
function asyncFunc() {
    try {
        doSomethingSync();
        return doSomethingAsync()
            .then(result => {
                ···
            });
    } catch (err) {
        return Promise.reject(err);
    }
}

//  Solution 2
function asyncFunc() {
    return Promise.resolve()
    .then(() => {
        doSomethingSync();
        return doSomethingAsync();
    })
    .then(result => {
        ···
    });
}

Unhandled rejected Promises

Before a rejection is reported, an event is dispatched that you can listen to:

window.addEventListener('unhandledrejection', event => ···);

The event is an instance of PromiseRejectionEvent whose two most important properties are:

  • promise: the Promise that was rejected

  • reason: the value with which the Promise was rejected

The following example demonstrates how this event works:

window.addEventListener("unhandledrejection", event => {
  // Prevent error output on the console:
  event.preventDefault();
  console.log("Reason: " + event.reason);
});

function foo() {
  Promise.reject("abc");
}
foo();
// Reason: abc

Last updated