Почему улов в асинхронном коде не ждет срабатывания кода? - PullRequest
1 голос
/ 23 мая 2019

существует ли какой-либо метод .catch(), как в случае с Promises для стиля кода async await?

Вот пример кода, написанного через Promise:

const apiURL = 'https://jsonplaceholder.typicode.com/todos/1';
const badURL = 'zhttps://wcaf.fajfkajf.gg'

function getData(url){
  fetch(url)
    .then(response => response.json())
    .then(json => console.log(json))
      .catch( err => console.log('cannot load api'))
}
  
getData(apiURL);
getData(badURL);

Простая функция для загрузки данных и, если нет, отображения основного сообщения об ошибке. Теперь я пытался переписать это в код стиля async/await, проблема была в том, что я не мог найти способ написать это с помощью catch()


Лучше всего было попробовать try - catch, но часть catch не работает:

const apiURL = 'https://jsonplaceholder.typicode.com/todos/1';
const badURL = 'zhttps://wcaf.fajfkajf.gg'

async function getData(url){
  const response = await fetch(url);
  try {
     const json = await response.json();
     console.log(json);
  } catch (e) {
     console.log('cannot load api');
  }
}
  
getData(apiURL);
getData(badURL);

Это прекрасно загружает объектный API, но, кажется, никогда не входит в блок catch{}, несмотря на неверный URL.

Есть идеи, что я делаю не так?

Ответы [ 2 ]

2 голосов
/ 23 мая 2019

Как указано в комментариях @ l-portet, это потому, что код внутри блока try { } на самом деле не дает сбой!

.json() вернет обещание, независимо от содержания разобранного основного текста , поэтому, даже если начальный fetch() не удастся, вы все равно можете вызвать .json() для него - хотя он полностью избыточен, поскольку он выиграл 'не возвращает ничего значащего.

Помещение запроса fetch() в блок try { } приводит к ожидаемому поведению:

const apiURL = 'https://jsonplaceholder.typicode.com/todos/1';
const badURL = 'zhttps://wcaf.fajfkajf.gg'

async function getData(url){
  try {
     const response = await fetch(url);
     const json = await response.json();
     console.log(json);
  } catch (e) {
     console.log('cannot load api');
  }
}
  
getData(apiURL);
getData(badURL);
1 голос
/ 23 мая 2019

Вы должны знать, что при выполнении функции async она всегда возвращает обещание , независимо от условия выхода из функции.

Если функция имеет явное return (или завершается без сбоя), обещание будет разрешено до возвращенного значения (или до undefined, если явного возврата не было), если Функция throws, обещание будет отклонено, передав брошенный объект error.

Зная, что вы можете просто обработать ошибку при использовании функции, например:

const apiURL = 'https://jsonplaceholder.typicode.com/todos/1';
const badURL = 'zhttps://wcaf.fajfkajf.gg'

async function getData(url){
  const response = await fetch(url);
  return await response.json();
}
  
getData(apiURL).then(data => console.log(data));
getData(badURL).catch(err => console.log('error:', err));

ИМХО тщательное рассмотрение ошибки там, где у вас есть сценарий использования функции, имеет больше смысла, поскольку обычно, когда вы ожидаете, что ошибка возникла, потому что у нас есть способ ее обработки (возможно, попробуйте другой URL API в этом примере) .

Один шаблон, который я использовал в последнее время, состоит в том, чтобы обернуть обещания так, чтобы они разрешали возвращать кортеж, в соответствии с соглашением [error, value] (аналогично тому, как язык программирования Go обрабатывает асинхронную ошибку), таким образом, для Например, вы можете обработать ошибку в конкретном вызове getData, например:

const apiURL = 'https://jsonplaceholder.typicode.com/todos/1';
const badURL = 'zhttps://wcaf.fajfkajf.gg'

async function getData(url){
  const response = await fetch(url);
  return await response.json();
}

// simple utility function
const safePromise = promise =>
  promise.then(data => [null, data]).catch(err => [err, undefined]);

(async () => {
  const [err, json] = await safePromise(getData(apiURL))
  if (err) {
    // handle the error
  }
  console.log(json)

  const [error, data] = await safePromise(getData(badURL))
  if (error) {
    console.log('Error:', error);
  }
})()

Проверьте следующую библиотеку, которая в основном поставляет этот шаблон:

...