> For the complete documentation index, see [llms.txt](https://strctr.gitbook.io/programming/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://strctr.gitbook.io/programming/01-languages/javascript/01-language/e-controls/e5-async/05-error-handling.md).

# 05. Error Handling

Существует несколько подходов к обработкам ошибок внутри асинхронных функций:

* `try-catch`,
* Использовать инструментарий Promise (`p.then()`, `p.catch()`, `Promise.try()`),
* Использовать утилиты, что бы в результате `await` вызова возвращать `[data, err]`.

## `try-catch`

Каждый вызов `await`, который может выбрасывать исключение необходимо оборачивать в `catch`:

```javascript
async function asyncFunc() {
  try {
    await otherAsyncFunc();
  } catch (err) {
    console.error(err);
  }
}

// Equivalent to:
function asyncFunc() {
  return otherAsyncFunc().catch(err => {
    console.error(err);
  });
}
```

## Error handling with Promises

При вызове `await P` можно навешивать различные обработчики на `P` и тем самым использовать семантику `then()` и `catch()` вместе с `await`:

```javascript
async function Exec() {
    const res = await delay(2000)
        .then(() => 'resolved in 2000ms');
        .catch(() => 'error');

    return res;
}
```

## Structured return value

Можно перенять подход свойственный go где в результате вызова операции возвращается `data, err` написав функцию:

```javascript
// to.js
export default function to(promise) {
   return promise.then(
       data => [null, data]),
       err => [err, null]
   );
}
```

Тогда обработка асинхронного кода будет иметь вид:

```javascript
import to from "./to.js";

async function asyncTask(cb) {
  let err, user, savedTask;

  [err, user] = await to(UserModel.findById(1));
  if (!user) return cb("No user found");

  [err, savedTask] = await to(
    TaskModel({ userId: user.id, name: "Demo Task" })
  );
  if (err) return cb("Error occurred while saving task");

  if (user.notificationsEnabled) {
    const [err] = await to(
      NotificationService.sendNotification(user.id, "Task Created")
    );
    if (err) return cb("Error while sending notification");
  }

  cb(null, savedTask);
}
```

У этого подхода есть преимущество в том, что на деструкции можно использовать значения по умолчанию:

```javascript
const catchify = require("catchify");

async function example(promise) {
  const [error, value = { message: "Hello" }] = await catchify(promise);
  if (error) console.log(error);
  return value;
}
```

* [`await-to-js`](https://github.com/scopsy/await-to-js)
* [`catchify`](https://github.com/majgis/catchify)
