- PVSM.RU - https://www.pvsm.ru -

JavaScript. Работаем с исключениями и данными в конструкциях async-await без блоков try-catch

Появившиеся в JavaScript новые асинхроные конструкции async/await выглядят проще, чем Promise, и, конечно, значительно читабельнее, чем «callback-джунгли». Но одна вещь беспокоила меня — это использование try-catch. Сначала я подумал, что это не проблема, но, к несчастью, мне пришлось работать с цепочкой вызовов API, в которой каждый вызов API имел свое сообщение об ошибке, которое должно было прологировано. Вскоре я понял, что создаю «try/catch-джунгли», которые ничем не лучше «callback-джунглей».

Давайте рассмотрим этот Promise, который возвращает данные или исключение через 2 секунды в зависимости от параметра rejectPromise:

// api.js
const fetchData = async (duration, rejectPromise) => (
  new Promise((resolve, reject) => {
    setTimeout(() => {
      if (rejectPromise) {
        reject({
          error: 'Error Encountered',
          status: 'error'
        })
      }
      resolve({
        version: 1,
        hello: 'world',
      });
    }, duration);
  })
);

module.exports = {
  fetchData,
};

Типичное использование этой функции будет выглядеть так:

const { fetchData } = require('./api');

const callApi = async () => {
  try {
    const value = await fetchData(2000, false);
    console.info(value);
  } catch (error) {
    console.error(error);
  }
}

callApi();

/* 
 OUTPUT: 
 { version: 1, hello: 'world' } (rejectPromise=false)
 { error: 'Error Encountered', status: 'error' } (rejectPromise=true)
 */

Как вы можете видеть, когда параметр rejectPromise является ложным, Promise возвращает значение {version: 1, hello: 'world'}, а когда оно истинно, он вызывает исключение { error: 'Error Encountered', status: 'error' }.

Это типичная реализация async-await. Теперь мы попытаемся использовать Promise, чтобы сделать этот код более простым. Давайте напишем функцию-обертку, которая упростит нам обработку исключений.

// wrapper.js
const wrapper = promise => (
  promise
    .then(data => ({ data, error: null }))
    .catch(error => ({ error, data: null }))
);

module.exports = wrapper;

Мы можем видеть, что функция-обертка принимает Promise в качестве входного параметра и возвращает ошибку или даные с использовнаием конструкции then().catch(). Итак, давайте изменим исходный код с применением функции-обертки:

const { fetchData } = require('./api');
const wrapper = require('./wrapper');

const callApi = async () => {
  const { error, data } = await wrapper(fetchData(2000, false));
  if (!error) {
    console.info(data);
    return;
  }
  console.error(error);
}

callApi();

/* 
 OUTPUT: 
 { version: 1, hello: 'world' } (rejectPromise=false)
 { error: 'Error Encountered', status: 'error' } (rejectPromise=true)
 */

image — получаем тот же результат но более читабельным кодом.

Полезные ссылки.

1. Почему [не] надо использовать async/await [1]

Автор: apapacy

Источник [2]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/javascript/280508

Ссылки в тексте:

[1] Почему [не] надо использовать async/await: https://medium.com/@vkozulya/%D0%BF%D0%BE%D1%87%D0%B5%D0%BC%D1%83-%D0%BD%D0%B5-%D0%BD%D0%B0%D0%B4%D0%BE-%D0%B8%D1%81%D0%BF%D0%BE%D0%BB%D1%8C%D0%B7%D0%BE%D0%B2%D0%B0%D1%82%D1%8C-async-await-7e999c981049

[2] Источник: https://habr.com/post/358896/?utm_source=habrahabr&utm_medium=rss&utm_campaign=358896