Fetch: yuklanish jarayoni
Katta hajmdagi ma'lumotni yuklab olayotganda (masalan, katta fayl yoki video), foydalanuvchiga necha foiz yuklanganini ko'rsatish foydali. fetch buni response.body orqali โ oqim (stream) sifatida o'qish imkonini beradi.
fetch yuklab olish (download) jarayonini kuzatishga imkon beradi, ammo yuklab jo'natish (upload) jarayonini kuzata olmaydi โ buning uchun keyingi darsdagi XMLHttpRequest kerak bo'ladi.response.body โ ReadableStream
Oldingi darslarda javob tanasini response.json() yoki response.text() bilan bir martaga o'qidik. Ammo response.body โ bu ReadableStream obyekti: ma'lumotni bo'lak-bo'lak (chunk) o'qishga imkon beradigan maxsus oqim.
Aynan shu bo'laklarni sanab, umumiy hajmga solishtirib, yuklanish foizini hisoblashimiz mumkin.
getReader() bilan o'qish
Oqimdan o'qish uchun undan reader (o'quvchi) olamiz va read() metodini takroran chaqiramiz. Har chaqiruv bitta bo'lakni qaytaradi:
let response = await fetch('https://example.com/big-file');
const reader = response.body.getReader();
while (true) {
const { done, value } = await reader.read();
if (done) {
break; // oqim tugadi
}
// value โ Uint8Array turidagi navbatdagi bo'lak
console.log('Bo'lak olindi, bayt: ' + value.length);
}
reader.read() promise qaytaradi va u ikki maydonli obyekt bilan bajariladi:
doneโ agar oqim tugagan bo'lsatrue, aks holdafalse;valueโ navbatdagi ma'lumot bo'lagi (Uint8Arrayturidagi baytlar massivi).
Content-Length โ umumiy hajm
Foizni hisoblash uchun umumiy hajmni bilishimiz kerak. Buni server Content-Length sarlavhasida yuboradi:
let response = await fetch(url);
const contentLength = response.headers.get('Content-Length');
const total = parseInt(contentLength, 10);
console.log('Umumiy hajm: ' + total + ' bayt');
Content-Length har doim ham mavjud bo'lavermaydi โ masalan, server ma'lumotni siqilgan (gzip) yoki chunked ko'rinishda yuborsa, u yo'q yoki noaniq bo'lishi mumkin. Shuning uchun kodda uning yo'qligini ham hisobga oling.Progressni to'liq hisoblash
Endi hammasini birlashtiramiz: umumiy hajmni olamiz, bo'laklarni o'qib, qabul qilingan baytlarni sanaymiz va foizni chiqaramiz:
async function yuklabOl(url) {
let response = await fetch(url);
const reader = response.body.getReader();
// Umumiy hajm (agar mavjud bo'lsa)
const contentLength = +response.headers.get('Content-Length');
let receivedLength = 0; // qabul qilingan baytlar
let chunks = []; // bo'laklar massivi
while (true) {
const { done, value } = await reader.read();
if (done) {
break;
}
chunks.push(value);
receivedLength += value.length;
// Progressni chiqaramiz
if (contentLength) {
let percent = Math.round((receivedLength / contentLength) * 100);
console.log('Yuklandi: ' + percent + '%');
} else {
console.log('Yuklandi: ' + receivedLength + ' bayt');
}
}
return chunks;
}
Bu yerda har bir bo'lak chunks massiviga saqlanadi va receivedLength oshib boradi. Foiz โ qabul qilingan / umumiy * 100 formulasi bilan hisoblanadi.
Bo'laklarni birlashtirish
Barcha bo'laklar o'qib bo'lingach, ularni bitta massivga birlashtirib, so'ng matnga (yoki JSON'ga) aylantirishimiz mumkin:
// chunks โ Uint8Array bo'laklari massivi
// 1) Barcha baytlarni bitta massivga birlashtiramiz
let chunksAll = new Uint8Array(receivedLength);
let position = 0;
for (let chunk of chunks) {
chunksAll.set(chunk, position);
position += chunk.length;
}
// 2) Baytlarni matnga aylantiramiz
let result = new TextDecoder('utf-8').decode(chunksAll);
// 3) Agar JSON bo'lsa, tahlil qilamiz
let data = JSON.parse(result);
console.log(data);
TextDecoder โ baytlarni (Uint8Array) matnga aylantiradigan o'rnatilgan brauzer vositasi. UTF-8 kodlashda emoji va o'zbekcha harflar to'g'ri o'qiladi.Nima uchun oddiy usul yetarli emas?
Agar progress kerak bo'lmasa, oddiygina await response.json() yozish yetarli โ u ancha soddaroq. ReadableStream faqat yuklanish jarayonini kuzatish kerak bo'lganda ishlatiladi:
// Progress kerak bo'lmasa โ sodda:
let response = await fetch(url);
let data = await response.json();
// Progress kerak bo'lsa โ reader bilan:
let reader = response.body.getReader();
// ...bo'lak-bo'lak o'qish va foiz hisoblash
response.json() to'g'ri tanlov.Xulosa
response.bodyโ javob tanasini bo'lak-bo'lak o'qish imkonini beruvchi ReadableStream;response.body.getReader()โ oqimdan o'quvchi (reader) beradi;reader.read()โ har chaqiruvda{ done, value }qaytaradi:valueโ navbatdagi bo'lak (Uint8Array);- Umumiy hajm
Content-Lengthsarlavhasida keladi (ammo har doim ham mavjud emas); - Foiz =
qabul qilingan baytlar / umumiy hajm * 100; - Bo'laklar
Uint8Arrayga birlashtirilib,TextDecoderbilan matnga aylantiriladi; fetchfaqat yuklab olish progressini kuzatadi โ yuklab jo'natish (upload) uchunXMLHttpRequestkerak.