Fetch API пÑедоÑÑавлÑÐµÑ Ð¸Ð½ÑеÑÑÐµÐ¹Ñ JavaScript Ð´Ð»Ñ ÑабоÑÑ Ñ Ð·Ð°Ð¿ÑоÑами и оÑвеÑами HTTP. Ðн Ñакже пÑедоÑÑавлÑÐµÑ Ð³Ð»Ð¾Ð±Ð°Ð»ÑнÑй меÑод fetch()
, коÑоÑÑй позволÑÐµÑ Ð»ÐµÐ³ÐºÐ¾ и логиÑно полÑÑаÑÑ ÑеÑÑÑÑÑ Ð¿Ð¾ ÑеÑи аÑинÑ
Ñонно.
ÐÐ¾Ð´Ð¾Ð±Ð½Ð°Ñ ÑÑнкÑионалÑноÑÑÑ Ñанее доÑÑигалаÑÑ Ñ Ð¿Ð¾Ð¼Ð¾ÑÑÑ XMLHttpRequest
. Fetch пÑедÑÑавлÑÐµÑ Ñобой лÑÑÑÑÑ Ð°Ð»ÑÑеÑнаÑивÑ, коÑоÑÐ°Ñ Ð¼Ð¾Ð¶ÐµÑ Ð±ÑÑÑ Ð»ÐµÐ³ÐºÐ¾ иÑполÑзована дÑÑгими ÑеÑ
нологиÑми, Ñакими как Service Workers
. Fetch Ñакже обеÑпеÑÐ¸Ð²Ð°ÐµÑ ÐµÐ´Ð¸Ð½Ð¾Ðµ логиÑеÑкое меÑÑо Ð´Ð»Ñ Ð¾Ð¿ÑÐµÐ´ÐµÐ»ÐµÐ½Ð¸Ñ Ð´ÑÑгиÑ
ÑвÑзаннÑÑ
Ñ HTTP понÑÑий, Ñакие как CORS и ÑаÑÑиÑÐµÐ½Ð¸Ñ Ð´Ð»Ñ HTTP.
ÐбÑаÑиÑе внимание, fetch
ÑпеÑиÑикаÑÐ¸Ñ Ð¾ÑлиÑаеÑÑÑ Ð¾Ñ jQuery.ajax()
в оÑновном в двÑÑ
пÑнкÑаÑ
:
fetch()
не пеÑейдÑÑ Ð² ÑоÑÑоÑние "оÑклонено" из-за оÑвеÑа HTTP, коÑоÑÑй ÑÑиÑаеÑÑÑ Ð¾Ñибкой, даже еÑли оÑÐ²ÐµÑ HTTP 404 или 500. ÐмеÑÑо ÑÑого, он бÑÐ´ÐµÑ Ð²Ñполнен ноÑмалÑно (Ñ Ð·Ð½Ð°Ñением false в ÑÑаÑÑÑе ok
) и бÑÐ´ÐµÑ Ð¾ÑклонÑн ÑолÑко пÑи Ñбое ÑеÑи или еÑли ÑÑо-Ñо помеÑало запÑоÑÑ Ð²ÑполниÑÑÑÑ.fetch
не бÑÐ´ÐµÑ Ð¾ÑпÑавлÑÑÑ Ð¸Ð»Ð¸ полÑÑаÑÑ cookie ÑÐ°Ð¹Ð»Ñ Ñ ÑеÑвеÑа, в ÑезÑлÑÑаÑе Ñего запÑоÑÑ Ð±ÑдÑÑ Ð¾ÑÑÑеÑÑвлÑÑÑÑÑ Ð±ÐµÐ· пÑовеÑки подлинноÑÑи, ÑÑо пÑиведÑÑ Ðº неаÑÑенÑиÑиÑиÑованнÑм запÑоÑам, еÑли ÑÐ°Ð¹Ñ Ð¿Ð¾Ð»Ð°Ð³Ð°ÐµÑÑÑ Ð½Ð° пÑовеÑÐºÑ Ð¿Ð¾Ð»ÑзоваÑелÑÑкой ÑеÑÑии (Ð´Ð»Ñ Ð¾ÑпÑавки cookie Ñайлов в аÑгÑменÑе init options должно бÑÑÑ Ð·Ð°Ð´Ð°Ð½Ð¾ знаÑение ÑвойÑÑва credentials оÑлиÑное Ð¾Ñ Ð·Ð½Ð°ÑÐµÐ½Ð¸Ñ Ð¿Ð¾ ÑмолÑÐ°Ð½Ð¸Ñ omit
).ÐазовÑй запÑÐ¾Ñ Ð½Ð° полÑÑение даннÑÑ Ð´ÐµÐ¹ÑÑвиÑелÑно пÑоÑÑ Ð² наÑÑÑойке. ÐзглÑниÑе на ÑледÑÑÑий код:
fetch('http://example.com/movies.json') .then((response) => { return response.json(); }) .then((data) => { console.log(data); });
ÐдеÑÑ Ð¼Ñ Ð·Ð°Ð±Ð¸Ñаем JSON Ñайл по ÑеÑи и вÑводим его ÑодеÑжимое в конÑолÑ. СамÑй пÑоÑÑой ÑпоÑоб иÑполÑÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ fetch()
заклÑÑаеÑÑÑ Ð² вÑзове ÑÑой ÑÑнкÑии Ñ Ð¾Ð´Ð½Ð¸Ð¼ аÑгÑменÑом â ÑÑÑокой, ÑодеÑжаÑей пÑÑÑ Ðº ÑеÑÑÑÑÑ, коÑоÑÑй Ð²Ñ Ñ
оÑиÑе полÑÑиÑÑ â коÑоÑÐ°Ñ Ð²Ð¾Ð·Ð²ÑаÑÐ°ÐµÑ promise, ÑодеÑжаÑее оÑÐ²ÐµÑ (обÑÐµÐºÑ Response
).
ÐонеÑно, ÑÑо пÑоÑÑо HTTP-оÑвеÑ, а не ÑакÑиÑеÑкий JSON. ЧÑÐ¾Ð±Ñ Ð¸Ð·Ð²Ð»ÐµÑÑ ÑодеÑжимое Ñела JSON из оÑвеÑа, Ð¼Ñ Ð¸ÑполÑзÑем json()
меÑод (опÑеделÑн микÑином Body
, коÑоÑÑй Ñеализован в обÑекÑаÑ
Request
и Response
.)
Fetch-запÑоÑÑ ÐºÐ¾Ð½ÑÑолиÑÑÑÑÑÑ Ð¿Ð¾ÑÑедÑÑвом диÑекÑÐ¸Ð²Ñ connect-src
(Content Security Policy), а не диÑекÑивой извлекаемÑÑ
ÑеÑÑÑÑов.
ÐеÑод 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()
.
ЧÑÐ¾Ð±Ñ Ð±ÑаÑзеÑÑ Ð¼Ð¾Ð³Ð»Ð¸ оÑпÑавлÑÑÑ Ð·Ð°Ð¿ÑÐ¾Ñ Ñ ÑÑÑÑнÑми даннÑми (даже Ð´Ð»Ñ 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()
можно оÑпÑавлÑÑÑ 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-ÑлеменÑа <input type="file" />
, 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-ÑлеменÑа <input type="file" multiple />
, 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
. ÐÑли Ð²Ñ Ñ
оÑиÑе загÑÑзиÑÑ ÑекÑÑовÑй Ñайл и обÑабаÑÑваÑÑ ÐµÐ³Ð¾ по меÑе загÑÑзки поÑÑÑоÑно, Ñо на Ð²Ð°Ñ ÑамиÑ
ложиÑÑÑ Ð³ÑÑз оÑвеÑÑÑвенноÑÑи за обÑабоÑÐºÑ Ð²ÑеÑ
ÑпомÑнÑÑÑÑ
моменÑов. Ðак пÑимеÑ, далее пÑедÑÑавлен один из ÑпоÑобов подобной обÑабоÑки Ñ Ð¿Ð¾Ð¼Ð¾ÑÑÑ ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ð¿Ð¾ÑÑÑоÑного иÑеÑаÑоÑа (Ð´Ð»Ñ Ð¿ÑоÑÑоÑÑ Ð¿ÑинÑÑÑ ÑледÑÑÑие допÑÑениÑ: ÑекÑÑ Ð¿ÑиÑ
Ð¾Ð´Ð¸Ñ Ð² кодиÑовке 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()
promise бÑÐ´ÐµÑ Ð¾ÑклонÑн (reject) Ñ TypeError
, когда ÑлÑÑиÑÑÑ Ð¾Ñибка ÑеÑи или не бÑÐ´ÐµÑ ÑконÑигÑÑиÑован CORS на ÑÑоÑоне запÑаÑиваемого ÑеÑвеÑа, Ñ
оÑÑ Ð¾Ð±ÑÑно ÑÑо ознаÑÐ°ÐµÑ Ð¿ÑÐ¾Ð±Ð»ÐµÐ¼Ñ Ð´Ð¾ÑÑÑпа или аналогиÑнÑе â Ð´Ð»Ñ Ð¿ÑимеÑа, 404 не ÑвлÑеÑÑÑ ÑеÑевой оÑибкой. ÐÐ»Ñ Ð´Ð¾ÑÑовеÑной пÑовеÑки ÑÑпеÑноÑÑи fetch() бÑÐ´ÐµÑ Ð²ÐºÐ»ÑÑаÑÑ Ð¿ÑовеÑÐºÑ Ñого, ÑÑо promise ÑÑпеÑен (resolved), заÑем пÑовеÑÐºÑ Ñого, ÑÑо знаÑение ÑвойÑÑва Response.ok
ÑвлÑеÑÑÑ 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()
, и пеÑедаÑÑ ÐµÐ³Ð¾ в 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()
, ÑоздаÑÑий копии. Ðба меÑода ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ ÐºÐ¾Ð¿Ð¸Ð¸ пÑекÑаÑÑÑ ÑабоÑÑ Ñ Ð¾Ñибкой еÑли Ñело оÑигиналÑного запÑоÑа или оÑвеÑа Ñже бÑло пÑоÑиÑано, но ÑÑение Ñела клониÑованного оÑвеÑа или запÑоÑа не пÑиведÑÑ Ðº маÑкиÑовке оÑигиналÑного.
ÐнÑеÑÑÐµÐ¹Ñ Headers
позволÑÐµÑ Ð²Ð°Ð¼ ÑоздаÑÑ Ð²Ð°Ñ ÑобÑÑвеннÑй обÑÐµÐºÑ Ð·Ð°Ð³Ð¾Ð»Ð¾Ð²ÐºÐ¾Ð² ÑеÑез конÑÑÑÑкÑÐ¾Ñ Headers()
. ÐбÑÐµÐºÑ Ð·Ð°Ð³Ð¾Ð»Ð¾Ð²ÐºÐ¾Ð² - пÑоÑÑÐ°Ñ Ð¼ÑлÑÑикаÑÑа имÑн-знаÑений:
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",
});
СодеÑжимое Ð¼Ð¾Ð¶ÐµÑ Ð±ÑÑÑ Ð·Ð°Ð¿ÑоÑено и извлеÑено:
console.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
, но они пÑедоÑÑавлÑÑÑ Ð±Ð¾Ð»ÐµÐµ ÑдобнÑй 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
).request-no-cors: заÑиÑа обÑекÑа заголовков, полÑÑенного по запÑоÑÑ Ñозданного Ñ Request.mode
no-cors.response: заÑиÑа Headers полÑÑеннÑÑ
Ð¾Ñ Ð¾ÑвеÑа (Response.headers
).immutable: в оÑновном, иÑполÑзÑеÑÑÑ Ð² ServiceWorkers; Ð´ÐµÐ»Ð°ÐµÑ Ð¾Ð±ÑÐµÐºÑ Ð·Ð°Ð³Ð¾Ð»Ð¾Ð²ÐºÐ¾Ð² read-only.
ÐÑимеÑание: Ð²Ñ Ð½Ðµ можеÑе добавиÑÑ Ð¸Ð»Ð¸ ÑÑÑановиÑÑ request заÑиÑаемÑе Headers' заголовок Content-Length. ÐналогиÑно, вÑÑавка Set-Cookie в заголовок оÑвеÑа недопÑÑÑимо: ServiceWorkers не допÑÑкаÑÑ ÑÑÑановки cookies ÑеÑез ÑинÑезиÑованнÑе оÑвеÑÑ.
ÐбÑекÑÑ Ð¾ÑвеÑа
Ðак Ð²Ñ Ð²Ð¸Ð´ÐµÐ»Ð¸ вÑÑе, ÑкземплÑÑ Response
бÑÐ´ÐµÑ Ð²Ð¾Ð·Ð²ÑаÑÑн когда fetch() пÑÐ¾Ð¼Ð¸Ñ Ð±ÑÐ´ÐµÑ Ð¸Ñполнен.
СвойÑÑва обÑекÑа-оÑвеÑа коÑоÑÑе ÑаÑе вÑего иÑполÑзÑÑÑÑÑ:
Response.status
â ЦелоÑиÑленное (по ÑмолÑÐ°Ð½Ð¸Ñ 200) ÑодеÑÐ¶Ð¸Ñ ÐºÐ¾Ð´ ÑÑаÑÑÑа оÑвеÑа.Response.statusText
â СÑÑока (по ÑмолÑаниÑ"OK"), коÑоÑÐ°Ñ ÑооÑвеÑÑÑвÑÐµÑ HTTP ÐºÐ¾Ð´Ñ ÑÑаÑÑÑа.Response.ok
â как Ñказано Ñанее, ÑÑо коÑоÑкое ÑвойÑÑво Ð´Ð»Ñ ÑпÑоÑÐµÐ½Ð¸Ñ Ð¿ÑовеÑки на Ñо ÑÑо ÑÑаÑÑÑ Ð¾ÑвеÑа наÑ
одиÑÑÑ Ð³Ð´Ðµ-Ñо Ð¼ÐµÐ¶Ð´Ñ 200-299 вклÑÑиÑелÑно. ÐÑо ÑвойÑÑво Ñипа Boolean
.
Ðни Ñак же могÑÑ Ð±ÑÑÑ ÑÐ¾Ð·Ð´Ð°Ð½Ñ Ñ Ð¿Ð¾Ð¼Ð¾ÑÑÑ JavaScript, но ÑеалÑÐ½Ð°Ñ Ð¿Ð¾Ð»Ñза Ð¾Ñ ÑÑого еÑÑÑ ÑолÑко пÑи иÑполÑзовании ÑеÑвиÑ-воÑкеÑов
, когда Ð²Ñ Ð¿ÑедоÑÑавлÑеÑе ÑобÑÑвеннÑй оÑÐ²ÐµÑ Ð½Ð° запÑÐ¾Ñ Ñ Ð¿Ð¾Ð¼Ð¾ÑÑÑ Ð¼ÐµÑода respondWith()
:
const myBody = new Blob();
addEventListener("fetch", function (event) {
// ServiceWorker пеÑеÑ
ваÑÑÐ²Ð°ÐµÑ fetch
event.respondWith(
new Response(myBody, {
headers: { "Content-Type": "text/plain" },
}),
);
});
ÐонÑÑÑÑкÑÐ¾Ñ Response()
пÑÐ¸Ð½Ð¸Ð¼Ð°ÐµÑ Ð´Ð²Ð° необÑзаÑелÑнÑÑ
аÑгÑменÑа â Ñело Ð´Ð»Ñ Ð¾ÑвеÑа и обÑÐµÐºÑ init (аналогиÑнÑй ÑомÑ, коÑоÑÑй пÑÐ¸Ð½Ð¸Ð¼Ð°ÐµÑ Request()
)
ÐÑимеÑание: ÐеÑод error()
пÑоÑÑо возвÑаÑÐ°ÐµÑ Ð¾ÑÐ²ÐµÑ Ð¾Ð± оÑибке. ÐналогиÑно, redirect()
возвÑаÑÐ°ÐµÑ Ð¾ÑвеÑ, пÑиводÑÑий к пеÑенапÑÐ°Ð²Ð»ÐµÐ½Ð¸Ñ Ð½Ð° ÑказаннÑй URL. Ðни Ñакже оÑноÑÑÑÑÑ ÑолÑко к Service Workers.
ÐапÑÐ¾Ñ Ð¸ оÑÐ²ÐµÑ Ð¼Ð¾Ð³ÑÑ ÑодеÑжаÑÑ Ð´Ð°Ð½Ð½Ñе Ñела. Тело ÑвлÑеÑÑÑ ÑкземплÑÑом лÑбого из ÑледÑÑÑÐ¸Ñ Ñипов:
ArrayBuffer
ArrayBufferView
(Uint8Array и подобнÑе)Blob
/FilestringURLSearchParams
FormData
Body
пÑимеÑÑ Ð¾Ð¿ÑеделÑÐµÑ ÑледÑÑÑие меÑÐ¾Ð´Ñ Ð´Ð»Ñ Ð¸Ð·Ð²Ð»ÐµÑÐµÐ½Ð¸Ñ Ñела (ÑÐµÐ°Ð»Ð¸Ð·Ð¾Ð²Ð°Ð½Ñ ÐºÐ°Ðº Ð´Ð»Ñ Request
Ñак и Ð´Ð»Ñ Response
). ÐÑе они возвÑаÑаÑÑ promise, коÑоÑÑй в конеÑном иÑоге иÑполнÑеÑÑÑ Ð¸ вÑÐ²Ð¾Ð´Ð¸Ñ ÑодеÑжимое.
arrayBuffer()
blob()
json()
text()
formData()
ÐÑо Ð´ÐµÐ»Ð°ÐµÑ Ð¸ÑполÑзование неÑекÑÑовÑÑ Ð´Ð°Ð½Ð½ÑÑ Ð±Ð¾Ð»ÐµÐµ лÑгким, Ñем пÑи 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
, Request
, Response
или fetch()
в облаÑÑи видимоÑÑи Window
или Worker
. ÐÐ»Ñ Ð¿ÑимеÑа:
if (window.fetch) {
// запÑÑÑиÑÑ Ð¼Ð¾Ð¹ fetch запÑÐ¾Ñ Ð·Ð´ÐµÑÑ
} else {
// ÑделаÑÑ ÑÑо-Ñо Ñ XMLHttpRequest?
}
СмоÑÑиÑе Ñакже
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4