DevGang
Авторизоваться

Выполнение HTTP-запросов в Node.js с помощью node-fetch 

Веб-приложению часто требуется взаимодействовать с веб-серверами для получения различных ресурсов. Возможно, вам потребуется извлечь данные или отправить данные на внешний веб-сервер или API.

Используя клиентский JavaScript, этого можно достичь с помощью API fetch и функции window.fetch(). В NodeJS несколько пакетов / библиотек могут достичь одного и того же результата. Один из них - node-fetch.

node-fetch - это небольшой модуль, который позволяет нам использовать функцию fetch() в NodeJS, с функциональностью, очень похожей на нативный window.fetch(), но с некоторыми отличиями:

Начало работы с node-fetch

Чтобы использовать node-fetch в своем проекте, перейдите в каталог проекта и выполните:

npm install node-fetch

Чтобы использовать модуль в коде, используйте:

var fetch = require('node-fetch');

Как упоминалось ранее, функция fetch() в модуле node-fetch ведет себя очень похоже на window.fetch(). Его сигнатура:

fetch(url[, options])

Параметр url просто прямой URL ресурса который мы хотим запросить. Это должен быть абсолютный URL, иначе функция выдаст ошибку. Необязательный параметр options используется, когда мы хотим использовать что-либо, кроме простого GET запроса, но мы поговорим об этом более подробно позже.

Функция возвращает объект Response, содержащий полезные функции и информацию об ответе HTTP, например:

  1. text() - возвращает тело ответа в виде строки
  2. json() - анализирует тело ответа на объект JSON и выдает ошибку, если тело не может быть проанализировано
  3. status и statusText- содержат информацию о коде статуса HTTP
  4. ok - равно true, если status это код состояния 2xx (успешный запрос)
  5. headers - объект, содержащий заголовки ответа, к определенному заголовку можно получить доступ с помощью функции get().

Отправка запросов GET с использованием node-fetch

Есть два распространенных случая получения данных с веб-сервера. Возможно, вы захотите получить текст с веб-сервера, целую веб-страницу или данные с помощью REST API. Пакет node-fetch позволяет все это сделать.

Создайте каталог для вашего проекта и инициализируйте проект Node с настройками по умолчанию:

npm init -y

Это создаст файл package.json в каталоге. Затем установите node-fetch, как показано выше, и добавьте файл index.js.

Получение текста или веб-страниц

Сделаем простой GET запрос на главную страницу Google:

var fetch = require('node-fetch');

fetch('https://google.com')
        .then(res => res.text())
        .then(text => console.log(text))

В приведенном выше коде мы загружаем модуль node-fetch, а затем получаем домашнюю страницу Google. Единственный параметр, который мы добавили в функцию fetch() - это URL-адрес сервера, к которому мы отправляем HTTP-запрос. Поскольку node-fetch основан на обещаниях, мы объединяем в цепочку несколько функций .then(), чтобы помочь нам управлять ответом и данными из нашего запроса.

В этой строке мы ждем ответа от веб-сервера Google и конвертируем его в текстовый формат:

.then(res => res.text())

Здесь ждем результата предыдущего преобразования и выводим его в консоль:

.then(text => console.log(text))

Если мы запустим приведенный выше код из консоли:

node index.js

Мы получим всю HTML-разметку домашней страницы Google, зарегистрированную в консоли:

<!doctype html>
<html itemscope="" itemtype="http://schema.org/WebPage" lang="en-RS">
    <head>
        <meta charset="UTF-8">
        <meta content="origin" name="referrer">
        <!-- Rest of the page -->

Получение данных JSON из REST API

Другой распространенный вариант использования модуля node-fetch - получение данных с помощью REST API.

Мы получим поддельные данные пользователя из REST API JSONPlaceholder. Как и раньше, функция fetch() принимает URL-адрес сервера и ожидает ответа.

Давайте посмотрим, как это работает:

var fetch = require('node-fetch');

fetch('https://jsonplaceholder.typicode.com/users')
        .then(res => res.json())
        .then(json => {
            console.log("First user in the array:")
            console.log(json[0])
            console.log("Name of the first user in the array:")
            console.log(json[0].name)
})

Тело ответа HTTP содержит данные в формате JSON, а именно массив, содержащий информацию о пользователях. Имея это в виду, мы использовали функцию .json(), и это позволило нам легко получить доступ к отдельным элементам и их полям.

Запуск этой программы даст нам:

First element in the array:
{
  id: 1,
  name: 'Leanne Graham',
  username: 'Bret',
  email: 'Sincere@april.biz',
  address: {
    street: 'Kulas Light',
    suite: 'Apt. 556',
    city: 'Gwenborough',
    zipcode: '92998-3874',
    geo: { lat: '-37.3159', lng: '81.1496' }
  },
  phone: '1-770-736-8031 x56442',
  website: 'hildegard.org',
  company: {
    name: 'Romaguera-Crona',
    catchPhrase: 'Multi-layered client-server neural-net',
    bs: 'harness real-time e-markets'
  }
}

Name of the first person in the array:
Leanne Graham

Мы также могли напечатать весь JSON, возвращенный res.json().

Отправка запросов POST с помощью&nbsp;node-fetch

Мы также можем использовать эту функцию fetch() для публикации данных вместо их получения. Как мы упоминали ранее, что fetch() позволяет добавить дополнительный параметр для выполнения POST запросов к веб-серверу. Без этого необязательного параметра наш запрос по умолчанию является запросом GET.

Давайте добавим новый элемент в список задач JSONPlaceholder. Давайте добавим в этот список новый элемент для пользователя, у которого id равно 123. Сначала нам нужно создать объект todo, а затем преобразовать его в JSON при добавлении в поле body:

var fetch = require('node-fetch');

var todo = {
    userId: 123,
    title: "loren impsum doloris",
    completed: false
}

fetch('https://jsonplaceholder.typicode.com/todos', {
    method: 'POST',
    body: JSON.stringify(todo),
    headers: { 'Content-Type': 'application/json' }
})
        .then(res => res.json())
        .then(json => console.log(json))

Процесс очень похож на отправку GET запроса. Мы вызвали функцию fetch() с соответствующим URL-адресом и установили необходимые параметры, используя необязательный параметр функции fetch(). Раньше мы преобразовывали наш объект в строку в формате JSON перед его отправкой на веб-сервер с помощью JSON.stringify(). Затем, как и при получении данных, мы ждали ответа, конвертировали его в JSON и выводили на консоль.

Запуск кода дает нам результат:

{
  userId: 123,
  title: 'loren impsum doloris',
  completed: false,
  id: 201
}

Обработка исключений и ошибок

Наши запросы иногда могут завершаться неудачно по разным причинам - из-за ошибки в функции fetch(), проблем с Интернетом, внутренних ошибок сервера и других. Нам нужен способ справиться с этими ситуациями или, по крайней мере, уметь видеть, что они произошли.

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

var fetch = require('node-fetch');

var todo = {
    userId: 123,
    title: "loren impsum doloris",
    completed: false
}

fetch('https://jsonplaceholder.typicode.com/todos', {
    method: 'POST',
    body: JSON.stringify(todo),
    headers: { 'Content-Type': 'application/json' }
})
        .then(res => res.json())
        .then(json => console.log(json))
        .catch(err => console.log(err))

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

Мы должны помнить, что если наш ответ имеет код состояния 3xx / 4xx / 5xx, запрос либо не выполнен, либо клиенту необходимо предпринять дополнительные шаги.

А именно, коды состояния HTTP 3xx указывают на то, что клиенту необходимо предпринять дополнительные шаги, коды 4xx указывают на недопустимый запрос, а коды 5xx указывают на ошибки сервера. Все эти коды состояния говорят нам, что наш запрос не был успешным с практической точки зрения.

catch() не будет регистрировать ни один из этих случаев, потому что связь с сервером прошла успешно, т.е. мы сделали запрос и получили ответ успешно. Это означает, что нам необходимо предпринять дополнительные шаги, чтобы убедиться, что мы охватили ситуацию, когда связь клиент-сервер была успешной, но мы не получили ни одного из успешных (2xx) кодов состояния HTTP.

Распространенный способ убедиться, что неудачные запросы вызывают ошибку, - это создать функцию, которая проверяет HTTP-статус ответа от сервера. В этой функции, если код состояния не указывает на успех, мы можем выдать ошибку и catch() поймать ее.

Мы можем использовать ранее упомянутое поле ok объекта Response, которое равно true, если код состояния равен 2xx.

Посмотрим, как это работает:

var fetch = require('node-fetch');

function checkResponseStatus(res) {
    if(res.ok){
        return res
    }
    else {
        throw new Error(`The HTTP status of the reponse: ${res.status} (${res.statusText})`)
    }
}

fetch('https://jsonplaceholder.typicode.com/MissingResource')
        .then(checkResponseStatus)
        .then(res => res.json())
        .then(json => console.log(json))
        .catch(err => console.log(err))

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

Опять же, у вас должна быть стратегия обработки подобных ошибок, а не просто вывод на консоль.

Если все прошло, как ожидалось, и код состояния указывает на успех, программа продолжит работу, как и раньше.

Вывод

Выполнение запросов к веб-серверам - обычная задача веб-разработки, и в этой статье мы увидели, как мы можем сделать это эффективно, используя библиотеку node-fetch, которая делает API-интерфейс fetch из браузера совместимым с NodeJS.

В дополнение к этому мы также рассмотрели, как обрабатывать ошибки, которые могут возникнуть с HTTP-запросами.

Источник:

#JavaScript #NodeJS
Комментарии
Чтобы оставить комментарий, необходимо авторизоваться

Присоединяйся в тусовку

Поделитесь своим опытом, расскажите о новом инструменте, библиотеке или фреймворке. Для этого не обязательно становится постоянным автором.

Попробовать

Оплатив хостинг 25$ в подарок вы получите 100$ на счет

Получить