Что такое Fetch API в Javascript
Fetch API позволяет нам отправлять запросы на сервер и получать ответы. Он также предоставляет глобальный метод fetch(), упрощающий асинхронное получение ресурсов по сети.
Ниже приведен простой пример компонента реакции, который использует метод fetch для получения данных с сервера. Компонент «Продукты» получает «URL» в качестве реквизита. Внутри хука useEffect выполняется вызов fetch и обновляется состояние, которое затем отображает список извлеченных элементов.
const Products = ({ url }) => { const [data, setData] = useState(); const [error, setError] = useState(false); useEffect(() => { fetch(url) .then(response => setData(response.data)) .catch(error => setError(true)) }, [url]) if (!data) { return <p>No Products Found</p> } return ( <> { data.map(item => <li key={item.id}>{item.name}</li>) } </> ) }
Проблемы с приведенным выше кодом
Вышеупомянутый код будет работать отлично в большинстве случаев, но что, если компонент размонтируется или наш реквизит URL будет быстро меняться несколько раз? Например, если наш URL-адрес быстро изменится 3 раза, метод fetch будет вызываться 3 раза с 3 разными URL-адресами, и запросы будут занимать разное время, чтобы получить данные с сервера.
Итак, учитывая, что мы запускаем каждый запрос с разницей в 100 мс,
Первый запрос (для получения данных требуется 100 мс)
Выполняется при = 0 мс
Получает ответ при = 0 мс + 100 мс = 100 мс
Второй запрос (для получения данных требуется 500 мс)
Выполняется при = 100 мс
Получает ответ через = 100 мс + 500 мс = 600 мс
Третий запрос (возврат данных занимает 200 мс)
Выполняется при = 200 мс
Получает ответ через = 200 мс + 200 мс = 400 мс
Для приведенного выше примера через 100 мс мы вернем наш 1-й ответ. Затем через 400 мс придет третий ответ и, наконец, через 600 мс придет второй ответ. Таким образом, на самом деле, если мы запустим все эти 3 запроса на выборку, мы получим данные из второго, поскольку для их получения потребовалось немного больше времени. У нас есть данные по второму URL, а не по третьему, что означает, что наши данные не синхронизированы.
Это очень распространенный вариант использования, поскольку запросы в сети выполняются в разное время по разным причинам.
Решение проблемы
Чтобы избежать этого варианта использования, мы можем отменять запрос на выборку каждый раз, когда URL-адрес изменяется, используя функцию очистки useEffect, чтобы прервать запрос на выборку. Используя AbortController и передав сигнал контроллера в запросе на выборку, мы можем подключить AbortController к запросу на выборку. Затем просто в функции очистки мы можем вызвать функцию controller.abort(), чтобы отменить запрос при изменении URL-адреса. Таким образом, весь код внутри блоков then() и catch() вообще не будет выполняться.
Вот пример обновленного хука
useEffect(() => { const controller = new AbortController() fetch(url, { signal: controller.signal }) .then(response => setData(response.data)) .catch(error => setError(true)); return () => { controller.abort(); } }, [url])
Заключение
Таким образом, независимо от того, сколько раз URL-адрес меняет данные, они будут синхронизированы с последним URL-адресом, потому что до того, как будет сделан новый вызов выборки, предыдущий полностью прерывается.
Спасибо и надеюсь, вам понравилось читать эту статью.