fetch metodi yuklash jarayonini kuzatish imkonini beradi.
Diqqat qiling: hozirda fetch uchun yuborish jarayonini kuzatish imkoni yoâq. Bu maqsad uchun XMLHttpRequest dan foydalaning, uni keyinroq koârib chiqamiz.
Yuklash jarayonini kuzatish uchun response.body xususiyatidan foydalanishimiz mumkin. Bu ReadableStream â kelganda body ni qism-qism taqdim etadigan maxsus obyekt. Readable streamâlar Streams API spetsifikatsiyasida tasvirlangan.
response.text(), response.json() va boshqa metodlardan farqli oâlaroq, response.body oâqish jarayoni ustidan toâliq nazoratni beradi va biz istalgan paytda qancha isteâmol qilinganini hisoblashimiz mumkin.
response.body dan javobni oâqiydigan kodning eskizi:
// response.json() va boshqa metodlar o'rniga
const reader = response.body.getReader();
// body yuklanayotganda cheksiz siklda
while(true) {
// oxirgi qism uchun done true bo'ladi
// value - qism baytlarining Uint8Array si
const {done, value} = await reader.read();
if (done) {
break;
}
console.log(`${value.length} bayt qabul qilindi`)
}
await reader.read() chaqiruvining natijasi ikkita xususiyatga ega obyekt:
doneâ oâqish tugallangandatrue, aks holdafalse.valueâ baytlarning typed array:Uint8Array.
Streams API shuningdek for await..of sikli bilan ReadableStream ustida asinxron iteratsiyani tasvirlaydi, lekin u hali keng qoâllab-quvvatlanmaydi (brauzer muammolariga qarang), shuning uchun biz while siklini ishlatamiz.
Yuklash tugagunicha, yaâni done true boâlgunicha, biz siklda javob qismlarini qabul qilamiz.
Jarayonni yozib qoâyish uchun, har bir qabul qilingan value fragment uchun uning uzunligini hisoblagichga qoâshishimiz kerak.
Mana toâliq ishlaydigan misol, u javobni oladi va konsolda jarayonni yozadi, keyinroq batafsilroq tushuntirishlar keladi:
// 1-qadam: fetch'ni boshlash va reader olish
let response = await fetch('https://api.github.com/repos/javascript-tutorial/en.javascript.info/commits?per_page=100');
const reader = response.body.getReader();
// 2-qadam: umumiy uzunlikni olish
const contentLength = +response.headers.get('Content-Length');
// 3-qadam: ma'lumotlarni o'qish
let receivedLength = 0; // hozirda qabul qilingan baytlar soni
let chunks = []; // qabul qilingan ikkilik qismlar massivi (body ni tashkil etadi)
while(true) {
const {done, value} = await reader.read();
if (done) {
break;
}
chunks.push(value);
receivedLength += value.length;
console.log(`${contentLength} dan ${receivedLength} qabul qilindi`)
}
// 4-qadam: qismlarni yagona Uint8Array ga birlashtirish
let chunksAll = new Uint8Array(receivedLength); // (4.1)
let position = 0;
for(let chunk of chunks) {
chunksAll.set(chunk, position); // (4.2)
position += chunk.length;
}
// 5-qadam: stringga dekodlash
let result = new TextDecoder("utf-8").decode(chunksAll);
// Tugadi!
let commits = JSON.parse(result);
alert(commits[0].author.login);
Buni qadam-baqadam tushuntiraylik:
-
Biz
fetchni odatdagidek bajaramiz, lekinresponse.json()ni chaqirish oârniga, stream readerresponse.body.getReader()ni olamiz.Diqqat qiling, biz bir xil javobni oâqish uchun ikkala metoddan ham foydalana olmaymiz: natijani olish uchun yoki reader yoki response metodidan foydalaning.
-
Oâqishdan oldin,
Content-Lengthheaderâidan toâliq javob uzunligini bilishimiz mumkin.U cross-origin soârovlar uchun mavjud boâlmasligi mumkin (Fetch: Cross-Origin So'rovlari bobiga qarang) va, texnik jihatdan, server uni oârnatishi shart emas. Lekin odatda u oârnida turadi.
-
Tugagunicha
await reader.read()ni chaqiring.Biz javob qismlarini
chunksmassivida toâplaymiz. Bu muhim, chunki javob isteâmol qilingandan keyin, uniresponse.json()yoki boshqa yoâl bilan âqayta oâqishâ imkoni boâlmaydi (sinab koâring, xatolik boâladi). -
Oxirida bizda
chunksâUint8Arraybayt qismlari massivi bor. Biz ularni yagona natijaga birlashtirishimiz kerak. Afsuski, ularni birlashtiruvchi yagona metod yoâq, shuning uchun buni amalga oshiradigan kod bor:- Biz
chunksAll = new Uint8Array(receivedLength)yaratamiz â birlashtirilgan uzunlikka ega bir xil turdagi massiv. - Keyin har bir
chunkni birin-ketin nusxalash uchun.set(chunk, position)metodidan foydalanamiz.
- Biz
-
Bizda natija
chunksAllda bor. Bu bayt massivi, string emas.String yaratish uchun bu baytlarni talqin qilishimiz kerak. Oârnatilgan TextDecoder aynan shuni qiladi. Keyin kerak boâlsa uni
JSON.parseqilishimiz mumkin.Agar bizga string oârniga ikkilik kontent kerak boâlsa-chi? Bu yanada oddiy. 4 va 5-qadamlarni barcha qismlardan
Blobyaratadigan yagona qator bilan almashtiring:let blob = new Blob(chunks);
Oxirida bizda natija (string yoki blob, qaysi biri qulay boâlsa) va jarayonda progress-tracking bor.
Yana bir bor, diqqat qiling, bu yuborish jarayoni uchun emas (fetch bilan hozir yoâli yoâq), faqat yuklash jarayoni uchun.
Bundan tashqari, agar oâlcham nomaâlum boâlsa, siklda receivedLength ni tekshirishimiz va u maâlum chegaraga yetganda uni toâxtatishimiz kerak. Shunda chunks xotirani toâldirmaydi.
Izohlar
<code>yorlig'ini ishlating, bir nechta satrlar uchun - ularni<pre>yorlig'i bilan o'rab qo'ying, 10 satrdan ortiq bo'lsa - sandbox (plnkr, jsbin, codepenâ¦)