Что делает метод .json()
Если не сделать response.json() — приходит пустой массив. Исходя из этого у меня возник вопрос — что именно делает метод .json()? Превращает json формат в объект? но для этого же есть JSON.parse() и он мне не помог, когда я поставил его вместо .json. Заранее спасибо!
Отслеживать
задан 25 авг 2021 в 13:34
47 1 1 серебряный знак 6 6 бронзовых знаков
Привет, learn.javascript.ru/fetch тут подробно описано
25 авг 2021 в 13:35
и еще, что означает => это сокращенная запись функции что ли, но ведь нету круглых скобок даже. Или это уникальный синтаксис для промисов?
25 авг 2021 в 13:35
Спасибо за ответ, там написано только response.json() – декодирует ответ в формате JSON, мне это ни о чем не говорит.
Fetch
JavaScript может отправлять сетевые запросы на сервер и подгружать новую информацию по мере необходимости.
Например, мы можем использовать сетевой запрос, чтобы:
- Отправить заказ,
- Загрузить информацию о пользователе,
- Запросить последние обновления с сервера,
- …и т.п.
Для сетевых запросов из JavaScript есть широко известный термин «AJAX» (аббревиатура от Asynchronous JavaScript And XML). XML мы использовать не обязаны, просто термин старый, поэтому в нём есть это слово. Возможно, вы его уже где-то слышали.
Есть несколько способов делать сетевые запросы и получать информацию с сервера.
Метод fetch() — современный и очень мощный, поэтому начнём с него. Он не поддерживается старыми (можно использовать полифил), но поддерживается всеми современными браузерами.
let promise = fetch(url, [options])
- url – URL для отправки запроса.
- options – дополнительные параметры: метод, заголовки и так далее.
Без options это простой GET-запрос, скачивающий содержимое по адресу url .
Браузер сразу же начинает запрос и возвращает промис, который внешний код использует для получения результата.
Процесс получения ответа обычно происходит в два этапа.
Во-первых, promise выполняется с объектом встроенного класса Response в качестве результата, как только сервер пришлёт заголовки ответа.
На этом этапе мы можем проверить статус HTTP-запроса и определить, выполнился ли он успешно, а также посмотреть заголовки, но пока без тела ответа.
Промис завершается с ошибкой, если fetch не смог выполнить HTTP-запрос, например при ошибке сети или если нет такого сайта. HTTP-статусы 404 и 500 не являются ошибкой.
Мы можем увидеть HTTP-статус в свойствах ответа:
- status – код статуса HTTP-запроса, например 200.
- ok – логическое значение: будет true , если код HTTP-статуса в диапазоне 200-299.
let response = await fetch(url); if (response.ok) < // если HTTP-статус в диапазоне 200-299 // получаем тело ответа (см. про этот метод ниже) let json = await response.json(); >else
Во-вторых, для получения тела ответа нам нужно использовать дополнительный вызов метода.
Response предоставляет несколько методов, основанных на промисах, для доступа к телу ответа в различных форматах:
- response.text() – читает ответ и возвращает как обычный текст,
- response.json() – декодирует ответ в формате JSON,
- response.formData() – возвращает ответ как объект FormData (разберём его в следующей главе),
- response.blob() – возвращает объект как Blob (бинарные данные с типом),
- response.arrayBuffer() – возвращает ответ как ArrayBuffer (низкоуровневое представление бинарных данных),
- помимо этого, response.body – это объект ReadableStream, с помощью которого можно считывать тело запроса по частям. Мы рассмотрим и такой пример несколько позже.
Например, получим JSON-объект с последними коммитами из репозитория на GitHub:
let url = 'https://api.github.com/repos/javascript-tutorial/en.javascript.info/commits'; let response = await fetch(url); let commits = await response.json(); // читаем ответ в формате JSON alert(commits[0].author.login);
То же самое без await , с использованием промисов:
fetch('https://api.github.com/repos/javascript-tutorial/en.javascript.info/commits') .then(response => response.json()) .then(commits => alert(commits[0].author.login));
Для получения ответа в виде текста используем await response.text() вместо .json() :
let response = await fetch('https://api.github.com/repos/javascript-tutorial/en.javascript.info/commits'); let text = await response.text(); // прочитать тело ответа как текст alert(text.slice(0, 80) + '. ');
В качестве примера работы с бинарными данными, давайте запросим и выведем на экран логотип спецификации «fetch» (см. главу Blob, чтобы узнать про операции с Blob ):
let response = await fetch('/article/fetch/logo-fetch.svg'); let blob = await response.blob(); // скачиваем как Blob-объект // создаём
let img = document.createElement('img'); img.style = 'position:fixed;top:10px;left:10px;width:100px'; document.body.append(img); // выводим на экран img.src = URL.createObjectURL(blob); setTimeout(() => < // прячем через три секунды img.remove(); URL.revokeObjectURL(img.src); >, 3000);
Мы можем выбрать только один метод чтения ответа.
Если мы уже получили ответ с response.text() , тогда response.json() не сработает, так как данные уже были обработаны.
let text = await response.text(); // тело ответа обработано let parsed = await response.json(); // ошибка (данные уже были обработаны)
Заголовки ответа
Заголовки ответа хранятся в похожем на Map объекте response.headers .
Это не совсем Map , но мы можем использовать такие же методы, как с Map , чтобы получить заголовок по его имени или перебрать заголовки в цикле:
let response = await fetch('https://api.github.com/repos/javascript-tutorial/en.javascript.info/commits'); // получить один заголовок alert(response.headers.get('Content-Type')); // application/json; charset=utf-8 // перебрать все заголовки for (let [key, value] of response.headers) < alert(`$= $`); >
Заголовки запроса
Для установки заголовка запроса в fetch мы можем использовать опцию headers . Она содержит объект с исходящими заголовками, например:
let response = fetch(protectedUrl, < headers: < Authentication: 'secret' >>);
Есть список запрещённых HTTP-заголовков, которые мы не можем установить:
- Accept-Charset , Accept-Encoding
- Access-Control-Request-Headers
- Access-Control-Request-Method
- Connection
- Content-Length
- Cookie , Cookie2
- Date
- DNT
- Expect
- Host
- Keep-Alive
- Origin
- Referer
- TE
- Trailer
- Transfer-Encoding
- Upgrade
- Via
- Proxy-*
- Sec-*
Эти заголовки обеспечивают достоверность данных и корректную работу протокола HTTP, поэтому они контролируются исключительно браузером.
POST-запросы
Для отправки POST -запроса или запроса с другим методом, нам необходимо использовать fetch параметры:
- method – HTTP метод, например POST ,
- body – тело запроса, одно из списка:
- строка (например, в формате JSON),
- объект FormData для отправки данных как form/multipart ,
- Blob / BufferSource для отправки бинарных данных,
- URLSearchParams для отправки данных в кодировке x-www-form-urlencoded , используется редко.
Чаще всего используется JSON.
Например, этот код отправляет объект user как JSON:
let user = < name: 'John', surname: 'Smith' >; let response = await fetch('/article/fetch/post/user', < method: 'POST', headers: < 'Content-Type': 'application/json;charset=utf-8' >, body: JSON.stringify(user) >); let result = await response.json(); alert(result.message);Заметим, что так как тело запроса body – строка, то заголовок Content-Type по умолчанию будет text/plain;charset=UTF-8 .
Но, так как мы посылаем JSON, то используем параметр headers для отправки вместо этого application/json , правильный Content-Type для JSON.
Отправка изображения
Мы можем отправить бинарные данные при помощи fetch , используя объекты Blob или BufferSource .
В этом примере есть элемент , на котором мы можем рисовать движением мыши. При нажатии на кнопку «Отправить» изображение отправляется на сервер:
Заметим, что здесь нам не нужно вручную устанавливать заголовок Content-Type , потому что объект Blob имеет встроенный тип ( image/png , заданный в toBlob ). При отправке объектов Blob он автоматически становится значением Content-Type .
Функция submit() может быть переписана без async/await , например, так:
function submit() < canvasElem.toBlob(function(blob) < fetch('/article/fetch/post/image', < method: 'POST', body: blob >) .then(response => response.json()) .then(result => alert(JSON.stringify(result, null, 2))) >, 'image/png'); >Итого
Типичный запрос с помощью fetch состоит из двух операторов await :
let response = await fetch(url, options); // завершается с заголовками ответа let result = await response.json(); // читать тело ответа в формате JSONfetch(url, options) .then(response => response.json()) .then(result => /* обрабатываем результат */)- response.status – HTTP-код ответа,
- response.ok – true , если статус ответа в диапазоне 200-299.
- response.headers – похожий на Map объект с HTTP-заголовками.
Методы для получения тела ответа:
- response.text() – возвращает ответ как обычный текст,
- response.json() – декодирует ответ в формате JSON,
- response.formData() – возвращает ответ как объект FormData (кодировка form/multipart, см. следующую главу),
- response.blob() – возвращает объект как Blob (бинарные данные с типом),
- response.arrayBuffer() – возвращает ответ как ArrayBuffer (низкоуровневые бинарные данные),
Опции fetch , которые мы изучили на данный момент:
- method – HTTP-метод,
- headers – объект с запрашиваемыми заголовками (не все заголовки разрешены),
- body – данные для отправки (тело запроса) в виде текста, FormData , BufferSource , Blob или UrlSearchParams .
В следующих главах мы рассмотрим больше параметров и вариантов использования fetch .
Задачи
Получите данные о пользователях GitHub
Создайте асинхронную функцию getUsers(names) , которая получает на вход массив логинов пользователей GitHub, запрашивает у GitHub информацию о них и возвращает массив объектов-пользователей.
Информация о пользователе GitHub с логином USERNAME доступна по ссылке: https://api.github.com/users/USERNAME .
В песочнице есть тестовый пример.
- На каждого пользователя должен приходиться один запрос fetch .
- Запросы не должны ожидать завершения друг друга. Надо, чтобы данные приходили как можно быстрее.
- Если какой-то запрос завершается ошибкой или оказалось, что данных о запрашиваемом пользователе нет, то функция должна возвращать null в массиве результатов.
Чтобы получить сведения о пользователе, нам нужно вызвать fetch(‘https://api.github.com/users/USERNAME’) .
Если ответ приходит cо статусом 200 , то вызываем метод .json() , чтобы прочитать JS-объект.
А если запрос завершается ошибкой или код статуса в ответе отличен от 200, то мы просто возвращаем null в массиве результатов.
async function getUsers(names) < let jobs = []; for(let name of names) < let job = fetch(`https://api.github.com/users/$`).then( successResponse => < if (successResponse.status != 200) < return null; >else < return successResponse.json(); >>, failResponse => < return null; >); jobs.push(job); > let results = await Promise.all(jobs); return results; >Пожалуйста, обратите внимание: вызов .then прикреплён к fetch , чтобы, когда ответ получен, сразу начинать считывание данных с помощью .json() , не дожидаясь завершения других запросов.
Если бы мы использовали await Promise.all(names.map(name => fetch(. ))) и вызывали бы .json() на результатах запросов, то пришлось бы ждать, пока завершатся все из них. Вызывая .json() сразу после каждого fetch , мы добились того, что считывание присланных по каждому запросу данных происходит независимо от других запросов.
Это пример того, как относительно низкоуровневое Promise API может быть полезным, даже если мы в основном используем async/await в коде.
fetch ( )
С помощью функции fetch ( ) можно отправлять сетевые запросы на сервер — как получать, так и отправлять данные. Метод возвращает промис с объектом ответа, где находится дополнительная информация (статус ответа, заголовки) и ответ на запрос.
Как понять
Скопировать ссылку «Как понять» Скопировано
Браузер предоставляет глобальный API для работы с запросами и ответами HTTP. Раньше для подобной работы использовался XMLHttpRequest, однако fetch ( ) более гибкая и мощная альтернатива, он понятнее и проще в использовании из-за того, что использует Promise .
Как пишется
Скопировать ссылку «Как пишется» Скопировано
Функция fetch ( ) принимает два параметра:
- url — адрес, по которому нужно сделать запрос;
- options (необязательный) — объект конфигурации, в котором можно настроить метод запроса, тело запроса, заголовки и многое другое.
По умолчанию вызов fetch ( ) делает GET-запрос по указанному адресу. Базовый вызов для получения данных можно записать таким образом:
fetch('http://jsonplaceholder.typicode.com/posts')fetch('http://jsonplaceholder.typicode.com/posts')Результатом вызова fetch ( ) будет Promise , в котором будет содержаться специальный объект ответа Response . У этого объекта есть два важных для нас поля:
- ok — принимает состояние true или false и сообщает об успешности запроса;
- json — метод, вызов которого, возвращает результат запроса в виде json.
В следующем примере используем .then ( ) — обработчик результата, полученного от асинхронной операции. Обработчик дождётся ответа от сервера, принимает ответ, и, в данном случае, неявно возвратит ответ, обработанный методом .json();
fetch('http://jsonplaceholder.typicode.com/posts') // функция then вернет другой промис (их можно чейнить). Когда отрезолвится промис (r.json()), который вернула функция then, будет вызван следующий колбек в цепочке .then((response) => response.json()) // Получим ответ в виде массива из объектов [, , , . ]fetch('http://jsonplaceholder.typicode.com/posts') // функция then вернет другой промис (их можно чейнить). Когда отрезолвится промис (r.json()), который вернула функция then, будет вызван следующий колбек в цепочке .then((response) => response.json()) // Получим ответ в виде массива из объектов [, , , . ]С помощью второго аргумента options можно передать настройки запроса. Например, можно изменить метод и добавить тело запроса, если мы хотим не получать, а отправлять данные. Так же в запрос можно добавить заголовки в виде объекта или специального класса Headers .
const newPost = title: 'foo', body: 'bar', userId: 1,> fetch('https://jsonplaceholder.typicode.com/posts', method: 'POST', // Здесь так же могут быть GET, PUT, DELETE body: JSON.stringify(newPost), // Тело запроса в JSON-формате headers: // Добавляем необходимые заголовки 'Content-type': 'application/json; charset=UTF-8', >,>) .then((response) => response.json()) .then((data) => console.log(data) // >)const newPost = title: 'foo', body: 'bar', userId: 1, > fetch('https://jsonplaceholder.typicode.com/posts', method: 'POST', // Здесь так же могут быть GET, PUT, DELETE body: JSON.stringify(newPost), // Тело запроса в JSON-формате headers: // Добавляем необходимые заголовки 'Content-type': 'application/json; charset=UTF-8', >, >) .then((response) => response.json()) .then((data) => console.log(data) // >)Cookies
Скопировать ссылку «Cookies» Скопировано
По умолчанию fetch ( ) запросы не включают в себя cookies и потому авторизованные запросы на сервере могут не пройти. Для этого необходимо добавить в настройку поле credentials :
fetch('https://somesite.com/admin', method: 'GET', // или 'same-origin' если можно делать такие запросы только в пределах этого домена credentials: 'include',>)fetch('https://somesite.com/admin', method: 'GET', // или 'same-origin' если можно делать такие запросы только в пределах этого домена credentials: 'include', >)Обработка ошибок
Скопировать ссылку «Обработка ошибок» Скопировано
Любой ответ на запрос через fetch ( ) (например HTTP-код 400, 404 или 500) переводит Promise в состояние fulfilled. Промис перейдёт в состояние rejected только если запрос не случился из-за сбоя сети или что-то помешало выполнению fetch ( ) .
// Запрос вернет ошибку 404 Not Foundfetch('https://jsonplaceholder.typicode.com/there-is-no-such-route').catch( () => console.log('Error occurred!') >) // Никогда не выполнится// Запрос вернет ошибку 404 Not Found fetch('https://jsonplaceholder.typicode.com/there-is-no-such-route').catch( () => console.log('Error occurred!') > ) // Никогда не выполнитсяЧтобы обработать ошибку запроса, необходимо обращать внимание на поле ok в объекте ответа Response . В случае ошибки запроса оно будет равно false .
fetch('https://jsonplaceholder.typicode.com/there-is-no-such-route') .then((response) => // Проверяем успешность запроса и выкидываем ошибку if (!response.ok) throw new Error('Error occurred!') > return response.json() >) // Теперь попадём сюда, т.к выбросили ошибку .catch((err) => console.log(err) >) // Error: Error occurred!fetch('https://jsonplaceholder.typicode.com/there-is-no-such-route') .then((response) => // Проверяем успешность запроса и выкидываем ошибку if (!response.ok) throw new Error('Error occurred!') > return response.json() >) // Теперь попадём сюда, т.к выбросили ошибку .catch((err) => console.log(err) >) // Error: Error occurred!На практике
Скопировать ссылку «На практике» Скопировано
Егор Огарков советует
Скопировать ссылку «Егор Огарков советует» Скопировано
Использование Fetch
Fetch API предоставляет интерфейс JavaScript для работы с запросами и ответами HTTP. Он также предоставляет глобальный метод fetch() (en-US), который позволяет легко и логично получать ресурсы по сети асинхронно.
Подобная функциональность ранее достигалась с помощью XMLHttpRequest . Fetch представляет собой лучшую альтернативу, которая может быть легко использована другими технологиями, такими как Service Workers (en-US). Fetch также обеспечивает единое логическое место для определения других связанных с HTTP понятий, такие как CORS и расширения для HTTP.
Обратите внимание, fetch спецификация отличается от jQuery.ajax() в основном в двух пунктах:
- Promise возвращаемый вызовом fetch() не перейдёт в состояние «отклонено» из-за ответа HTTP, который считается ошибкой, даже если ответ HTTP 404 или 500. Вместо этого, он будет выполнен нормально (с значением false в статусе ok ) и будет отклонён только при сбое сети или если что-то помешало запросу выполниться.
- По умолчанию, fetch не будет отправлять или получать cookie файлы с сервера, в результате чего запросы будут осуществляться без проверки подлинности, что приведёт к неаутентифицированным запросам, если сайт полагается на проверку пользовательской сессии (для отправки cookie файлов в аргументе init options должно быть задано значение свойства credentials отличное от значения по умолчанию omit ).
Примечание: 25 августа 2017 г. в спецификации изменилось значение по умолчанию свойства credentials на same-origin . Firefox применяет это изменение с версии 61.0b13.
Базовый запрос на получение данных действительно прост в настройке. Взгляните на следующий код:
fetch('http://example.com/movies.json') .then((response) => < return response.json(); >) .then((data) => < console.log(data); >);Здесь мы забираем JSON файл по сети и выводим его содержимое в консоль. Самый простой способ использования fetch() заключается в вызове этой функции с одним аргументом — строкой, содержащей путь к ресурсу, который вы хотите получить — которая возвращает promise, содержащее ответ (объект Response ).
Конечно, это просто HTTP-ответ, а не фактический JSON. Чтобы извлечь содержимое тела JSON из ответа, мы используем json() (en-US) метод (определён миксином Body , который реализован в объектах Request и Response .)
Примечание: Миксин Body имеет подобные методы для извлечения других типов контента; см. раздел Тело.
Fetch-запросы контролируются посредством директивы connect-src (Content Security Policy (en-US) ), а не директивой извлекаемых ресурсов.
Установка параметров запроса
Метод fetch() может принимать второй параметр — объект init , который позволяет вам контролировать различные настройки:
// Пример отправки POST запроса: async function postData(url = "", data = >) // Default options are marked with * const response = await fetch(url, method: "POST", // *GET, POST, PUT, DELETE, etc. mode: "cors", // no-cors, *cors, same-origin cache: "no-cache", // *default, no-cache, reload, force-cache, only-if-cached credentials: "same-origin", // include, *same-origin, omit headers: "Content-Type": "application/json", // 'Content-Type': 'application/x-www-form-urlencoded', >, redirect: "follow", // manual, *follow, error referrerPolicy: "no-referrer", // no-referrer, *client body: JSON.stringify(data), // body data type must match "Content-Type" header >); return await response.json(); // parses JSON response into native JavaScript objects > postData("https://example.com/answer", answer: 42 >).then((data) => console.log(data); // JSON data parsed by `response.json()` call >);
С подробным описанием функции и полным списком параметров вы можете ознакомиться на странице fetch() (en-US).
Отправка запроса с учётными данными
Чтобы браузеры могли отправлять запрос с учётными данными (даже для cross-origin запросов), добавьте credentials: ‘include’ в объект init , передаваемый вами в метод fetch() :
fetch("https://example.com", credentials: "include", >);
Если вы хотите отправлять запрос с учётными данными только если URL принадлежит одному источнику (origin) что и вызывающий его скрипт, добавьте credentials: ‘same-origin’.
// Вызывающий скрипт принадлежит источнику 'https://example.com' fetch("https://example.com", credentials: "same-origin", >);
Напротив, чтобы быть уверенным, что учётные данные не передаются с запросом, используйте credentials: ‘omit’:
fetch("https://example.com", credentials: "omit", >);
Отправка данных в формате JSON
При помощи fetch() (en-US) можно отправлять POST-запросы в формате JSON.
const url = "https://example.com/profile"; const data = username: "example" >; try const response = await fetch(url, method: "POST", // или 'PUT' body: JSON.stringify(data), // данные могут быть 'строкой' или ! headers: "Content-Type": "application/json", >, >); const json = await response.json(); console.log("Успех:", JSON.stringify(json)); > catch (error) console.error("Ошибка:", error); >
Загрузка файла на сервер
На сервер можно загрузить файл, используя комбинацию HTML-элемента , FormData() и fetch() .
const formData = new FormData(); const fileField = document.querySelector('input[type="file"]'); formData.append("username", "abc123"); formData.append("avatar", fileField.files[0]); try const response = await fetch("https://example.com/profile/avatar", method: "PUT", body: formData, >); const result = await response.json(); console.log("Успех:", JSON.stringify(result)); > catch (error) console.error("Ошибка:", error); >
Загрузка нескольких файлов на сервер
На сервер можно загрузить несколько файлов, используя комбинацию HTML-элемента , FormData() и fetch() .
const formData = new FormData(); const photos = document.querySelector('input[type="file"][multiple]'); formData.append("title", "Мой отпуск в Вегасе"); for (let i = 0; i photos.files.length; i++) formData.append("photos", photos.files[i]); > try const response = await fetch("https://example.com/posts", method: "POST", body: formData, >); const result = await response.json(); console.log("Успех:", JSON.stringify(result)); > catch (error) console.error("Ошибка:", error); >
Обработка текстового файла построчно
Фрагменты данных, получаемые из ответа, не разбиваются на строки автоматически (по крайней мере с достаточной точностью) и представляют собой не строки, а объекты Uint8Array (en-US). Если вы хотите загрузить текстовый файл и обрабатывать его по мере загрузки построчно, то на вас самих ложится груз ответственности за обработку всех упомянутых моментов. Как пример, далее представлен один из способов подобной обработки с помощью создания построчного итератора (для простоты приняты следующие допущения: текст приходит в кодировке UTF-8 и ошибки получения не обрабатываются).
async function* makeTextFileLineIterator(fileURL) const utf8Decoder = new TextDecoder("utf-8"); let response = await fetch(fileURL); let reader = response.body.getReader(); let value: chunk, done: readerDone > = await reader.read(); chunk = chunk ? utf8Decoder.decode(chunk) : ""; let re = /\n|\r|\r\n/gm; let startIndex = 0; let result; for (;;) let result = re.exec(chunk); if (!result) if (readerDone) break; > let remainder = chunk.substr(startIndex); ( value: chunk, done: readerDone > = await reader.read()); chunk = remainder + (chunk ? utf8Decoder.decode(chunk) : ""); startIndex = re.lastIndex = 0; continue; > yield chunk.substring(startIndex, result.index); startIndex = re.lastIndex; > if (startIndex chunk.length) //последняя строка не имеет символа перевода строки в конце yield chunk.substr(startIndex); > > for await (let line of makeTextFileLineIterator(urlOfFile)) processLine(line); >
Проверка успешности запроса
В методе fetch() (en-US) promise будет отклонён (reject) с TypeError , когда случится ошибка сети или не будет сконфигурирован CORS на стороне запрашиваемого сервера, хотя обычно это означает проблемы доступа или аналогичные — для примера, 404 не является сетевой ошибкой. Для достоверной проверки успешности fetch() будет включать проверку того, что promise успешен (resolved), затем проверку того, что значение свойства Response.ok (en-US) является true. Код будет выглядеть примерно так:
try const response = await fetch("flowers.jpg"); if (!response.ok) throw new Error("Ответ сети был не ok."); > const myBlob = await response.blob(); const objectURL = URL.createObjectURL(myBlob); myImage.src = objectURL; > catch (error) console.log("Возникла проблема с вашим fetch запросом: ", error.message); >Составление своего объекта запроса
Вместо передачи пути ресурса, который вы хотите запросить вызовом fetch(), вы можете создать объект запроса, используя конструктор Request() (en-US), и передать его в fetch() аргументом:
const myHeaders = new Headers(); const myInit = method: "GET", headers: myHeaders, mode: "cors", cache: "default", >; const myRequest = new Request("flowers.jpg", myInit); const response = await fetch(myRequest); const myBlob = await response.blob(); const objectURL = URL.createObjectURL(myBlob); myImage.src = objectURL;
Конструктор Request() принимает точно такие же параметры, как и метод fetch(). Вы даже можете передать существующий объект запроса для создания его копии:
const anotherRequest = new Request(myRequest, myInit);
Довольно удобно, когда тела запроса и ответа используются единожды (прим.пер.: «are one use only»). Создание копии как показано позволяет вам использовать запрос/ответ повторно, при изменении опций init, при желании. Копия должна быть сделана до прочтения тела, а чтение тела в копии также пометит его прочитанным в исходном запросе.
Примечание: Также есть метод clone() (en-US), создающий копии. Оба метода создания копии прекратят работу с ошибкой если тело оригинального запроса или ответа уже было прочитано, но чтение тела клонированного ответа или запроса не приведёт к маркировке оригинального.
Заголовки
Интерфейс Headers (en-US) позволяет вам создать ваш собственный объект заголовков через конструктор Headers() (en-US). Объект заголовков — простая мультикарта имён-значений:
const content = "Hello World"; const myHeaders = new Headers(); myHeaders.append("Content-Type", "text/plain"); myHeaders.append("Content-Length", content.length.toString()); myHeaders.append("X-Custom-Header", "ProcessThisImmediately");
То же может быть достигнуто путём передачи массива массивов или литерального объекта конструктору:
const myHeaders = new Headers( "Content-Type": "text/plain", "Content-Length": content.length.toString(), "X-Custom-Header": "ProcessThisImmediately", >);
Содержимое может быть запрошено и извлечено:
.log(myHeaders.has("Content-Type")); // true console.log(myHeaders.has("Set-Cookie")); // false myHeaders.set("Content-Type", "text/html"); myHeaders.append("X-Custom-Header", "AnotherValue"); console.log(myHeaders.get("Content-Length")); // 11 console.log(myHeaders.get("X-Custom-Header")); // ["ProcessThisImmediately", "AnotherValue"] myHeaders.delete("X-Custom-Header"); console.log(myHeaders.get("X-Custom-Header")); // [ ]
Некоторые из этих операций могут быть использованы только в ServiceWorkers (en-US), но они предоставляют более удобный API для манипуляции заголовками.
Все методы Headers выбрасывают TypeError, если имя используемого заголовка не является валидным именем HTTP Header. Операции мутации выбросят TypeError если есть защита от мутации (смотрите ниже) (прим.пер.: «if there is an immutable guard»). В противном случае они прерываются молча. Например:
const myResponse = Response.error(); try myResponse.headers.set("Origin", "http://mybank.com"); > catch (e) console.log("Не могу притвориться банком!"); >
Хорошим вариантом использования заголовков является проверка корректности типа контента перед его обработкой. Например:
try const response = await fetch(myRequest); const contentType = response.headers.get("content-type"); if (!contentType || !contentType.includes("application/json")) throw new TypeError("Ой, мы не получили JSON!"); > const json = await response.json(); /_ Дальнейшая обработка JSON _/; > catch (error) console.log(error); >Защита
С тех пор как заголовки могут передаваться в запросе, приниматься в ответе и имеют различные ограничения в отношении того, какая информация может и должна быть изменена, заголовки имеют свойство guard. Это не распространяется на Web, но влияет на то, какие операции мутации доступны для объекта заголовков.
none: по умолчанию.request: защита объекта заголовков, полученного по запросу ( Request.headers (en-US)).request-no-cors: защита объекта заголовков, полученного по запросу созданного с Request.mode no-cors.response: защита Headers полученных от ответа ( Response.headers (en-US)).immutable: в основном, используется в ServiceWorkers; делает объект заголовков read-only.
Примечание: вы не можете добавить или установить request защищаемые Headers’ заголовок Content-Length. Аналогично, вставка Set-Cookie в заголовок ответа недопустимо: ServiceWorkers не допускают установки cookies через синтезированные ответы.
Как вы видели выше, экземпляр Response будет возвращён когда fetch() промис будет исполнен.
Свойства объекта-ответа которые чаще всего используются:
Response.status (en-US) — Целочисленное (по умолчанию 200) содержит код статуса ответа. Response.statusText (en-US) — Строка (по умолчанию»OK»), которая соответствует HTTP коду статуса. Response.ok (en-US) — как сказано ранее, это короткое свойство для упрощения проверки на то что статус ответа находится где-то между 200-299 включительно. Это свойство типа Boolean (en-US).
Они так же могут быть созданы с помощью JavaScript, но реальная польза от этого есть только при использовании сервис-воркеров (en-US), когда вы предоставляете собственный ответ на запрос с помощью метода respondWith() (en-US):
const myBody = new Blob(); addEventListener("fetch", function (event) // ServiceWorker перехватывает fetch event.respondWith( new Response(myBody, headers: "Content-Type": "text/plain" >, >), ); >);
Конструктор Response() принимает два необязательных аргумента — тело для ответа и объект init (аналогичный тому, который принимает Request() (en-US))
Примечание: Метод error() (en-US) просто возвращает ответ об ошибке. Аналогично, redirect() (en-US) возвращает ответ, приводящий к перенаправлению на указанный URL. Они также относятся только к Service Workers.
Тело
Запрос и ответ могут содержать данные тела. Тело является экземпляром любого из следующих типов:
Body примесь определяет следующие методы для извлечения тела (реализованы как для Request так и для Response ). Все они возвращают promise, который в конечном итоге исполняется и выводит содержимое.
Это делает использование нетекстовых данных более лёгким, чем при XMR.
В запросе можно установить параметры для отправки тела запроса:
const form = new FormData(document.getElementById("login-form")); fetch("/login", method: "POST", body: form, >);
Параметры request и response (and by extension the fetch() function), по возможности возвращают корректные типы данных. Параметр request также автоматически установит Content-Type в заголовок, если он не был установлен из словаря.
Функция обнаружения
Поддержка Fetch API может быть обнаружена путём проверки наличия Headers (en-US), Request , Response или fetch() (en-US) в области видимости Window или Worker . Для примера:
if (window.fetch) // запустить мой fetch запрос здесь > else // сделать что-то с XMLHttpRequest? >
Смотрите также
- ServiceWorker API
- HTTP CORS
- HTTP
- Полифил Fetch
- Примеры работы с Fetch на GitHub
Found a content problem with this page?
- Edit the page on GitHub.
- Report the content issue.
- View the source on GitHub.
This page was last modified on 6 янв. 2024 г. by MDN contributors.
Your blueprint for a better internet.