Fetch
Ссылаться на:Developers.Google.com/Web/updates…
Некоторые очень старые программы все еще могут использовать XHR, например:
const request = new XMLHttpRequest()
request.responseType = 'json'
request.open('GET', '/url', true)
request.onload = () => {
console.log(request.response)
}
request.onerror = () => {
console.log('shits happen!')
}
request.send(null)
Таким образом, использование XHR для асинхронного доступа и чтения ресурсов очень громоздко.По сравнению с Fetch(), он позволяет создавать сетевой доступ, аналогичный XHR, но использует более простой и чистый API, не требует многократных обратных вызовов и запоминает сложные API XHR. Нижний уровень Fetch API реализуется через промисы.
XMLHttpRequest
Относительно полный XMLHttpRequest должен прослушивать по крайней мере два события (onload, onerror) для реализации обратных вызовов успеха и отказа, а также вызывать open() и send().
function reqListener() {
var data = JSON.parse(this.responseText);
console.log(data);
}
function reqError(err) {
console.log('Fetch Error :-S', err);
}
var oReq = new XMLHttpRequest();
oReq.onload = reqListener;
oReq.onerror = reqError;
oReq.open('get', './api/some.json', true);
oReq.send();
Fetch
Простой пример Fetch выглядит следующим образом:
fetch('./api/some.json')
.then(
function(response) {
if (response.status !== 200) {
console.log('Looks like there was a problem. Status Code: ' +
response.status);
return;
}
// Examine the text in the response
response.json().then(function(data) {
console.log(data);
});
}
)
.catch(function(err) {
console.log('Fetch Error :-S', err);
});
Синтаксис Fetch более семантический и простой для понимания. В приведенном выше примере мы сначала оцениваем код состояния ответа.Если он равен 200, мы преобразуем ответ в JSON.
Ответ, возвращаемый запросом fetch(), является объектом Stream, поэтому, когда мы вызываем response.json, возвращается объект Promise, поскольку объект потока читается асинхронно.
Fetch оптимизирует код с помощью асинхронности
Поскольку нижний уровень Fetch реализован с помощью Promise, мы можем напрямую использовать асинхронность для оптимизации приведенного выше кода, уменьшения количества обратных вызовов и сделать его более семантичным и простым для понимания.
async function geturl(){
try{
let res = await fetch('./api/some.json')
if(res.status == 200){
console.log(await res.text())
}
} catch(err){
console.log(err)
}
}
Метаданные ответа
В приведенном выше примере мы узнали о статусе объекта Response и о том, как преобразовать объект ответа в объект JSON. Давайте посмотрим на другие метаданные объекта Response:
fetch('users.json').then(function(response) {
console.log(response.headers.get('Content-Type'));
console.log(response.headers.get('Date'));
console.log(response.status);
console.log(response.statusText);
console.log(response.type);
console.log(response.url);
});
Тип ответа
Когда мы инициируем запрос Fetch, возвращаемый ответ будет иметь свойство response.type (базовый, корсовый, непрозрачный). Атрибут response.type указывает источник асинхронного ресурса и соответствующий метод обработки.
Когда мы делаем запрос того же источника, тип ответа является базовым, и вы можете прочитать всю информацию из ответа.
Если мы посещаем доменное имя другого происхождения и возвращаем соответствующий заголовок ответа COR, то тип запроса — cors. cors очень похож на basic, за исключением того, что вы не можете получить к нему доступ в ответе corsCache-Control
,Content-Language
,Content-Type
,Expires
,Last-Modified
иPragma
Когда мы инициируем запрос к доменному имени другого происхождения, если возвращаемый заголовок ответа не содержит информации CORS, то тип, соответствующий этому ответу, является непрозрачным типом. Непрозрачный ответ не может прочитать возвращенные данные, статус или даже определить, был ли запрос успешным.
Мы можем настроить режим запроса Fetch и запроса на возврат соответствующего типа ответа.Существуют следующие ответы:
- same-origin возвращает только запросы того же происхождения, другие типы будут отклонены
- cors получает запросы с одинаковым и другим происхождением и возвращает ответ с заголовком CORs.
- cors-with-forced-preflight выполнит проверку безопасности перед отправкой запроса
- no-cors используется для инициирования запросов из разных источников без заголовков CORS и возвращает непрозрачный ответ. Но в настоящее время этот тип можно использовать только в Service Worker, а не в window.fetch.
fetch('http://some-site.com/cors-enabled/some.json', {mode: 'cors'})
.then(function(response) {
return response.text();
})
.then(function(text) {
console.log('Request successful', text);
})
.catch(function(error) {
log('Request failed', error)
});
Цепочка обязательств
Поскольку ответ, возвращаемый Fetch, реализован на основе промиса, мы можем соединить несколько промисов в виде цепочки, как показано ниже:
function status(response) {
if (response.status >= 200 && response.status < 300) {
return Promise.resolve(response)
} else {
return Promise.reject(new Error(response.statusText))
}
}
function json(response) {
return response.json()
}
fetch('users.json')
.then(status)
.then(json)
.then(function(data) {
console.log('Request succeeded with JSON response', data);
}).catch(function(error) {
console.log('Request failed', error);
});
Конечно, мы также можем использовать асинхронность для оптимизации кода.
async function geturl(url){
try {
let res = await fetch(url)
if(res.status >= 200 && res.status < 300){
console.log('Request succeeded with JSON response', await res.json())
}
}catch (err){
console.log(err)
}
}
geturl('users.json')
Отправить запрос
Когда мы используем Fetch для инициирования запроса Post, нам нужно вручную установить параметр метода и параметр тела следующим образом:
fetch(url, {
method: 'post',
headers: {
"Content-type": "application/x-www-form-urlencoded; charset=UTF-8"
},
body: 'foo=bar&lorem=ipsum'
})
.then(json)
.then(function (data) {
console.log('Request succeeded with JSON response', data);
})
.catch(function (error) {
console.log('Request failed', error);
});
Если параметр метода не указан явно, запрос Get по умолчанию
Отправить запрос с куки
Если мы хотим передать параметр cookie в асинхронный запрос, нам нужно явно указать параметр учетных данных:
fetch(url, {
credentials: 'include'
})