11-bo‘lim
Ma'lumot olish
useEffect bilan so'rov yuborish, yuklanish va xato holatlari, poyga holati va uni AbortController bilan hal qilish.
Ushbu bo‘lim mundarijasi
Ilova ma'lumotni serverdan oladi. Node.js darsligida server tomonini yozgan edik - endi mijoz tomonini ko'ramiz.
Uchta holat #
Har qanday so'rovda uch holat bo'ladi: yuklanmoqda, xato, tayyor.
import { useState, useEffect } from "react";
import { createServer } from "node:http";
import { chiz, kut, matn } from "./dom-muhit.mjs";
const server = createServer((sorov, javob) => {
javob.writeHead(200, { "Content-Type": "application/json" });
javob.end(JSON.stringify({ ism: "Malika", ball: 88 }));
});
server.listen(0);
const asos = `http://localhost:${server.address().port}`;
function Profil({ manzil }) {
const [malumot, malumotniOzgartir] = useState(null);
const [yuklanmoqda, yuklanishniOzgartir] = useState(true);
const [xato, xatoniOzgartir] = useState(null);
useEffect(() => {
let bekor = false;
async function ol() {
yuklanishniOzgartir(true);
xatoniOzgartir(null);
try {
const javob = await fetch(manzil);
if (!javob.ok) throw new Error(`holat ${javob.status}`);
const natija = await javob.json();
if (!bekor) malumotniOzgartir(natija);
} catch (x) {
if (!bekor) xatoniOzgartir(x.message);
} finally {
if (!bekor) yuklanishniOzgartir(false);
}
}
ol();
return () => { bekor = true; };
}, [manzil]);
if (yuklanmoqda) return <p id="holat">Yuklanmoqda...</p>;
if (xato) return <p id="holat">Xato: {xato}</p>;
return <p id="holat">{malumot.ism}: {malumot.ball}</p>;
}
await chiz(<Profil manzil={asos} />);
console.log("boshida:", matn("#holat"));
await kut();
console.log("javobdan keyin:", matn("#holat"));
server.close();
boshida: Yuklanmoqda...
javobdan keyin: Malika: 88
Uch holat uchun uchta alohida useState. Bu eng oddiy va eng
tushunarli shakl.
Ko'p qo'llanmada faqat ma'lumot saqlanadi:
const [malumot, ozgartir] = useState(null);
Muammo: null ikki xil ma'noni bildiradi - "hali yuklanmadi" va
"topilmadi". Foydalanuvchi bo'sh ekranni ko'radi va nima
bo'layotganini bilmaydi.
Uchala holatni ham ochiq saqlang. Aks holda interfeys "sinmagan, lekin tushunarsiz" bo'lib qoladi.
Xatoni qayta ishlash #
import { useState, useEffect } from "react";
import { createServer } from "node:http";
import { chiz, kut, matn } from "./dom-muhit.mjs";
const server = createServer((sorov, javob) => {
if (sorov.url === "/yoq") {
javob.writeHead(404, { "Content-Type": "application/json" });
javob.end(JSON.stringify({ xato: "topilmadi" }));
return;
}
javob.writeHead(200, { "Content-Type": "application/json" });
javob.end(JSON.stringify({ holat: "yaxshi" }));
});
server.listen(0);
const asos = `http://localhost:${server.address().port}`;
function Yuklovchi({ manzil }) {
const [holat, ozgartir] = useState("yuklanmoqda");
useEffect(() => {
let bekor = false;
fetch(manzil)
.then((j) => {
if (!j.ok) throw new Error(`server ${j.status} qaytardi`);
return j.json();
})
.then((m) => { if (!bekor) ozgartir(`tayyor: ${m.holat}`); })
.catch((x) => { if (!bekor) ozgartir(`xato: ${x.message}`); });
return () => { bekor = true; };
}, [manzil]);
return <p id="holat">{holat}</p>;
}
await chiz(<Yuklovchi manzil={`${asos}/bor`} />);
await kut();
console.log("mavjud yo'l:", matn("#holat"));
await chiz(<Yuklovchi key="2" manzil={`${asos}/yoq`} />);
await kut();
console.log("yo'q yo'l:", matn("#holat"));
server.close();
mavjud yo'l: tayyor: yaxshi
yo'q yo'l: xato: server 404 qaytardi
Bu juda ko'p xatoga sabab bo'ladi: fetch faqat tarmoq
uzilganda rad etadi.
Server 404 yoki 500 qaytarsa, fetch uni muvaffaqiyat
deb biladi va .catch ishlamaydi.
Shuning uchun javob.ok ni qo'lda tekshirish kerak:
if (!javob.ok) throw new Error(`holat ${javob.status}`);
ok - holat kodi 200 va 299 orasida bo'lsa true.
Buni unutsangiz, 404 sahifasining HTML ini JSON deb o'qishga
urinasiz va chalkash xato olasiz.
Poyga holati #
import { useState, useEffect } from "react";
import { chiz, kut } from "./dom-muhit.mjs";
const izlar = [];
function sekinSorov(nom, kechikish) {
return new Promise((yechim) => setTimeout(() => yechim(nom), kechikish));
}
function Yomon({ so }) {
const [natija, ozgartir] = useState("");
useEffect(() => {
const kechikish = so === "birinchi" ? 80 : 10;
sekinSorov(so, kechikish).then((n) => {
izlar.push(`yozildi: ${n}`);
ozgartir(n);
});
}, [so]);
return <p id="natija">{natija}</p>;
}
await chiz(<Yomon so="birinchi" />);
await chiz(<Yomon so="ikkinchi" />);
await kut(150);
console.log(izlar.join("\n"));
console.log("ekranda:", document.querySelector("#natija").textContent);
yozildi: ikkinchi
yozildi: birinchi
ekranda: birinchi
Ekranda birinchi qoldi - garchi foydalanuvchi oxirgi marta
ikkinchi ni so'ragan bo'lsa ham.
Sodir bo'lgan narsa:
birinchiso'raldi - u sekin (80 ms);ikkinchiso'raldi - u tez (10 ms) va birinchi bo'lib keldi;- Keyin
birinchining javobi kelib, natijani ustiga yozdi.
Natijada foydalanuvchi eskirgan ma'lumotni ko'radi. Haqiqiy qidiruv maydonida bu doim sodir bo'ladi: har harfda yangi so'rov ketadi va ular turli tezlikda qaytadi.
Yechim - yuqoridagi misollarda ishlatilgan bekor bayrog'i:
tozalovchi funksiya uni true qiladi va eskirgan javob holatni
o'zgartirmaydi.
Keyingi bo'limda buni AbortController bilan ham ko'ramiz - u
so'rovning o'zini to'xtatadi.
Tuzatilgan shakl #
import { useState, useEffect } from "react";
import { chiz, kut } from "./dom-muhit.mjs";
function sekinSorov(nom, kechikish) {
return new Promise((yechim) => setTimeout(() => yechim(nom), kechikish));
}
function Yaxshi({ so }) {
const [natija, ozgartir] = useState("");
useEffect(() => {
let bekor = false;
const kechikish = so === "birinchi" ? 80 : 10;
sekinSorov(so, kechikish).then((n) => {
if (!bekor) ozgartir(n);
});
return () => { bekor = true; };
}, [so]);
return <p id="natija">{natija}</p>;
}
await chiz(<Yaxshi so="birinchi" />);
await chiz(<Yaxshi so="ikkinchi" />);
await kut(150);
console.log("ekranda:", document.querySelector("#natija").textContent);
ekranda: ikkinchi
Endi ekranda oxirgi so'ralgan qiymat turibdi.
bekor bayrog'i tozalovchi funksiyada true bo'ladi, shuning
uchun eskirgan javob e'tiborsiz qoladi.
AbortController #
import { useState, useEffect } from "react";
import { createServer } from "node:http";
import { chiz, kut, matn } from "./dom-muhit.mjs";
const server = createServer((sorov, javob) => {
setTimeout(() => {
javob.writeHead(200, { "Content-Type": "application/json" });
javob.end(JSON.stringify({ natija: sorov.url.slice(1) }));
}, 30);
});
server.listen(0);
const asos = `http://localhost:${server.address().port}`;
function Qidiruv({ so }) {
const [natija, ozgartir] = useState("kutilmoqda");
useEffect(() => {
const boshqaruvchi = new AbortController();
fetch(`${asos}/${so}`, { signal: boshqaruvchi.signal })
.then((j) => j.json())
.then((m) => ozgartir(m.natija))
.catch((x) => {
if (x.name !== "AbortError") ozgartir(`xato: ${x.message}`);
});
return () => boshqaruvchi.abort();
}, [so]);
return <p id="natija">{natija}</p>;
}
await chiz(<Qidiruv so="birinchi" />);
await chiz(<Qidiruv so="ikkinchi" />);
await kut(150);
console.log("ekranda:", matn("#natija"));
server.close();
ekranda: ikkinchi
AbortController bayroqdan bir qadam ilgari boradi: u so'rovni
haqiqatan to'xtatadi, ya'ni tarmoq ham bo'shaydi.
Bekor qilingan so'rov AbortError bilan rad etiladi - uni
oddiy xatodan ajratish kerak, chunki bu kutilgan hol.
Yuqoridagi kod to'g'ri, lekin uzun. Va u hali keshni, qayta urinishni, sahifalashni qamrab olmadi.
Haqiqiy loyihalarda odatda tayyor yechim olinadi:
| Vosita | Izoh |
|---|---|
TanStack Query | Eng mashhuri; kesh, qayta urinish, yangilash |
SWR | Yengilroq, soddaroq |
Next.js kabi freymvorklar | Ma'lumot olish ichiga qurilgan |
Lekin ular sehr emas: ichkarida aynan shu naqshlar bor. Qo'lda bir marta yozib ko'rgan bo'lsangiz, kutubxona nima qilayotganini tushunasiz va muammo chiqqanda uni tuzata olasiz.
- Uch holatli ma'lumot oluvchi komponent yozing.
javob.okni tekshirmasdan,404da nima bo'lishini ko'ring.- Tekshiruvni qo'shib, xatoni to'g'ri ushlang.
- Ikki so'rovni turli tezlikda yuborib, poyga holatini yasang.
bekorbayrog'i bilan uni to'g'rilang.AbortControllerbilan so'rovni to'xtating.AbortErrorni boshqa xatolardan ajrating.- Bog'liqliklar ro'yxatiga manzilni qo'shing.
- Yuklanish holatida xabar ko'rsating.
- Xato holatida qayta urinish tugmasini qo'shing.
Xulosa #
- Har bir so'rovda uch holat: yuklanmoqda, xato, tayyor.
fetch404va500da rad etmaydi -javob.okni qo'lda tekshiring.- Tez o'zgaradigan so'rovlarda poyga holati paydo bo'ladi: eski javob yangisining ustiga yozadi.
- Yechim - tozalovchi funksiyadagi
bekorbayrog'i yokiAbortController. AbortError- kutilgan hol, uni alohida ajrating.- Amalda
TanStack Querykabi kutubxona ishlatiladi, lekin ichkarida aynan shu naqshlar.
Keyingi bo'limda useRef ni o'rganamiz.
O‘qish tarixini saqlamoqchimisiz?
Tizimga kirsangiz, tugatgan bo‘limlaringiz saqlanadi va qoldirgan joyingizdan davom etasiz.
Xatolik topdingizmi?
Imlo xatosi, ishlamaydigan kod yoki noto‘g‘ri ma‘lumotni ko‘rsangiz - bizga xabar bering. Har bir xabar administrator tomonidan ko‘rib chiqiladi.