# 04.ii Promise.catch()

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

```javascript
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:

```javascript
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:

```javascript
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` обработчике:

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

Решение:

```javascript
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:

```javascript
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

```javascript
//  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:

```javascript
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:

```javascript
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
```
