API-интерфейс Fetch

Fetch позволяет выполнять сетевые запросы, написав гораздо меньше кода, чем при использовании XMLHttpRequest, и реализует API обещаний под капотом.

Пример кода с использованием выборки:

fetch("./data/list.json")
  .then((response) => {
    console.log("resolved", response);
  })
  .catch((err) => {
    console.log("error retrieving data", err);
  });
  1. Fetch принимает в качестве аргумента конечную точку URL-адреса, из которой нужно получить данные. Это может быть внутренний или внешний ресурс.
  2. Fetch возвращает обещание, с которым можно справиться с помощью метода .then, который мы видели в предыдущем сообщении блога.
  3. Если обещание разрешено, запускается функция обратного вызова .then. Если обещание отклонено (например, возникла проблема с получением данных), запускается функция обратного вызова .catch.

Ошибки с конечной точкой URL

Интересно подчеркнуть, что в случае, если мы неправильно написали конечную точку URL, обещание все равно будет разрешено, но свойство statusText объекта ответа будет пустым.

Чтобы убедиться, что мы получили объект, содержащий фактические данные, мы можем проверить значение статуса запроса и, если оно отличается от 200, выделить ошибку (ниже мы увидим, как выдать ошибку, чтобы объект ошибки был пойман) .

fetch("./data/listsssss.json")
  .then((response) => {
    if (response.status !== 200) {
      console.log("there is an error");
    }
    console.log("resolved", response);
  })
  .catch((err) => {
    console.log("error retrieving data", err);
  });

Где мои данные?

Допустим, конечная точка написана правильно, и мы возвращаем объект данных, если вы console.log ответ заметите, что фактические данные там не найдены. Чтобы увидеть и использовать эти данные, нам нужно применить метод .json, который анализирует строку данных и возвращает объект js. Этот метод является частью объекта ответа, который мы получаем с помощью API выборки, и возвращает обещание. Это означает, что мы не можем сохранить его значение внутри переменной, как показано ниже:

let myData = response.json() THIS IS WROOOOOONG!

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

fetch("./data/list.json")
  .then((response) => {
    console.log("resolved", response);
return response.json();
  })
  .then((data) => {
    console.log(data);
  })
  .catch((err) => {
    console.log("error retrieving data", err);
  });

Одна вещь, которая могла бы быть очень простой, но я не хотел принимать как должное: и «ответ», и «данные» - произвольные слова. Да, я изменил «response» на «MarioRossi» на «MarioRossi», чтобы он выглядел более интересным, и код работал (тогда я подумал, что, возможно, было бы разумно вернуть текст, тем более, что я понимаю, что есть некоторые соглашения, чтобы сделать код более читаемым и понятным: - )).

API получения за три шага

Подводя итог, когда мы используем fetch:

  1. мы получаем данные, предоставляя конечную точку URL
  2. мы возвращаем обещание response.json
  3. мы связываем метод .then и, наконец, получаем доступ к данным

Прежде всего, код намного проще, чем написание XMLHttpRequest!

асинхронный / ожидание

Синтаксис async и await позволяет упростить и упростить цепочку обещаний. Чтобы сделать асинхронную функцию с помощью async, мы пишем:

let myAsyncFunction = async () => {
...here we write all the asynchronous code...
}

При добавлении ключевого слова async вся функция возвращает обещание. Мы можем доказать это, поместив функцию в переменную, а затем в console.log:

let newVariable = myAsyncFunction()
console.log(newVariable)

async / await хорошо работает с fetch, поскольку позволяет очень легко обрабатывать обещания. Давайте посмотрим:

Fetch возвращает обещание, и поэтому мы не можем сохранить объект результата внутри переменной. В качестве решения этой проблемы async содержит полезное ключевое слово «await»:

let myAsyncFunction = async () => {
  let response = await fetch("./data/list.json");
  console.log(response);
};

При добавлении ключевого слова await объект ответа не сохраняется в переменной ответа до тех пор, пока обещание не будет выполнено.

Переходя к ответу console.log, мы увидим, что фактические данные не видны и, как указано выше, нам нужно применить метод .json, который возвращает обещание. Опять же, мы можем выполнить обещание, используя ключевое слово «await»:

let myAsyncFunction = async () => {
  let response = await fetch("./data/list.json");
  let data = await response.json;
  console.log(data);
  return data;
};

Вызов myAsyncFunction () возвращает обещание, и, поскольку код внутри функции возвращает данные, мы можем применить метод .then, который будет принимать данные в качестве аргумента (мы описываем, что происходит в случае ошибки в следующем параграфе):

myAsyncFunction().then((data) => {
  console.log("resolved", data);
});

Поскольку это асинхронная функция, myAsyncFunction () не препятствует запуску остальной части кода, и мы можем доказать это с помощью следующего кода:

console.log("1");
console.log("2");
console.log("3");
myAsyncFunction()
  .then((data) => {
    console.log("resolved", data);
  })
  .catch((err) => {
    console.log("rejected", err);
  });
console.log("4");

В консоли мы увидим 1,2,3,4 и, наконец, объект ответа.

Синтаксис async / await не только позволяет нам более четко связывать обещания с ключевым словом await, но также позволяет хранить асинхронную функцию внутри переменной, что упрощает ее вызов.

Ошибки метания

В случае возникновения проблемы с синтаксисом файла json (допустим, мы забыли заключить ключ в двойные кавычки), тогда обещание, возвращаемое response.json, будет отклонено, а также обещание общей функции async будет . Это означает, что мы могли поймать ошибку. В приведенном ниже примере мы обращаемся к свойству error объекта err:

.catch((err) => {
    console.log("rejected", err.message);
  });

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

Чтобы этого не произошло, нам нужно вручную проверить статус ответа, и, если он отличается от 200 , мы выдаем ошибку. Это предотвратит «срабатывание» метода .json.

let myAsyncFunction = async () => {
  const response = await fetch("./data/lists.json");
  if (response.status !== 200) {
    throw new Error("cannot fetch data");
  }
  let data = await response.json();
  return data;
};
myAsyncFunction()
  .then((data) => {
    console.log("resolved", data);
  })
  .catch((err) => {
    console.log("rejected", err.message);
  });

Написав «выбросить новую ошибку», мы создаем новый объект ошибки. Каждый раз, когда мы генерируем ошибку внутри асинхронной функции, обещание, возвращаемое ею, отклоняется, и, таким образом, мы можем отловить ошибку.

Сообщение об ошибке теперь будет «невозможно получить данные».

Я надеюсь, что этот пост в блоге и предыдущий помогли немного лучше понять тему сетевых запросов.

Пожалуйста, оставьте комментарий ниже, если вы считаете, что некоторые части статьи можно улучшить, или у вас есть какие-либо мысли, которыми вы хотели бы поделиться по этой теме.