Mundarija (23)
- Bu darsda
- 1. Nega bu kerak?
- 2. fetch Node'da
- 2.1 Bir xil API, boshqa muhit
- 2.2 Asosiy so'rov va res.ok
- 2.3 Timeout sukut bo'yicha yo'q
- 3. fetch failed: asl sababni o'qish
- 4. Keep-alive va ulanishlar hovuzi
- 4.1 Har so'rov — yangi ulanishmi?
- 4.2 Parallel so'rovlar va hovuz
- 4.3 undici: Agent, Pool, dispatcher
- 4.4 Narxi va valyuta
- 5. axios, ky, ofetch — kerakmi?
- 6. CLI qadami: User-Agent (holat 46, 1-qism)
- 7. Ko'p uchraydigan xatolar
- 8. Mashqlar
- 1-mashq (oson): to'ldiring
- 2-mashq (o'rta): getJson
- 3-mashq (qiyin): parallellik chegarasi
- 4-mashq: CLI qadami
- 9. Real ishda
- Xulosa
- Manbalar
Node.js fetch va undici: timeout, xatolar, keep-alive va ulanishlar hovuzi
Qisqacha: Node 24 da
fetchglobal — brauzerdagi bilan bir xil API, ichida undici kutubxonasi (7.29.1). Uch narsani bilish shart:fetch404/500 da xato tashlamaydi (res.okni tekshirasiz); timeout sukut bo'yicha yo'q (AbortSignal.timeout); tarmoq xatosi har doimTypeError: fetch failed, asl sabab esaerror.causeda. Ulanishlarni undici o'zi qayta ishlatadi (keep-alive). Hovuzni boshqarish uchun npm'dagiundicipaketiningAgenti kerak — lekin u o'zfetchi bilan ishlatiladi. Biz sinadik: npm'dagi undici 8Agentini o'rnatilganfetchga bersak,invalid onRequestStart methodxatosi chiqadi.
Bu darsda
- Node'dagi
fetchbrauzerdagidan nimasi bilan farq qilishini bilasiz. res.ok,res.json(),AbortSignal.timeoutbilan xavfsiz so'rov yozasiz.fetch failedichidagi asl sababni (ECONNREFUSED,ENOTFOUND,bad port) o'qiy olasiz.- Keep-alive va ulanishlar hovuzi (pool) nima ekanini o'lchov bilan ko'rasiz; undici
Agentvadispatcherni ishlatasiz. - axios, ky, ofetch qachon kerakligini aniq ayta olasiz;
valyutaga User-Agent qo'shasiz.
Oldin bilishingiz kerak: fetch asoslari, Request, Response, Headers va fetch opsiyalari, Axios, timers va timers/promises chuqur, net, dns va tls.
1. Nega bu kerak?
valyuta kursni CBU API'dan oladi. 11-qismda brauzerda fetch ni o'rgangansiz, Axios darsida esa nega ko'p loyihalar axios o'rnatishini ko'rgansiz. Node'da 2022 yilgacha fetch umuman yo'q edi — node-fetch yoki axios o'rnatilardi.
Node 18 dan fetch global, Node 21 dan barqaror. valyuta ning prod bog'liqliklari 0 — HTTP klient ham o'rnatilmagan. Lekin "qutidagi" fetch ning ham o'z tuzoqlari bor. Ular serverda brauzerdagidan qimmatroq: brauzerda bitta foydalanuvchi kutadi, serverda — minglab so'rovlar navbati.
O'xshatish: taksi chaqirish. Har safar yangi mashina chaqirsangiz (yangi ulanish), haydovchi uzoqdan keladi. Bitta haydovchi sizni kutib tursa (keep-alive), keyingi safar darhol jo'naysiz. Bir vaqtda nechta mashina ishlatishni esa taksi parki (pool) hal qiladi.
2. fetch Node'da
2.1 Bir xil API, boshqa muhit
Node'dagi fetch — brauzerdagi fetch ning standart API'si: Request, Response, Headers, AbortSignal. Farqlar muhitdan keladi:
| Brauzer | Node 24 | |
|---|---|---|
| CORS | bor — server ruxsat bermasa javob yopiq | yo'q — Node istalgan manzilga so'raydi |
| Cookie | brauzer o'zi saqlaydi va yuboradi | saqlanmaydi; set-cookie ni o'zingiz o'qiysiz |
| HTTP kesh | brauzer keshi | yo'q |
User-Agent |
brauzer nomi | node |
| Ichida | brauzer tarmoq qatlami | undici (process.versions.undici — 7.29.1) |
Oxirgi qatorni Node runtime darsida ko'rgansiz: undici — Node bilan birga keladigan HTTP klient. U node:http dan alohida, noldan yozilgan.
2.2 Asosiy so'rov va res.ok
Quyidagi blok kichik lokal server ochadi va unga uch xil so'rov yuboradi. Server qismiga qaramang (25-qismda o'rganasiz) — fetch qatorlariga qarang. Blok Node uchun — o'z terminalingizda ishga tushiring:
import { createServer } from "node:http";
const server = createServer((req, res) => {
if (req.url === "/yoq") {
res.writeHead(404, { "content-type": "application/json" });
return res.end('{"xato":"topilmadi"}');
}
if (req.url === "/html") {
return res.end("<h1>Xizmat ishlamayapti</h1>");
}
res.writeHead(200, { "content-type": "application/json" });
res.end('[{"Ccy":"USD","Rate":"11903.15"}]');
});
await new Promise((ok) => server.listen(0, "127.0.0.1", ok));
const base = `http://127.0.0.1:${server.address().port}`;
const ok = await fetch(`${base}/`);
console.log(ok.status, ok.ok, ok.headers.get("content-type"));
console.log(await ok.json());
const missing = await fetch(`${base}/yoq`);
console.log(missing.status, missing.ok, await missing.text());
try {
await (await fetch(`${base}/html`)).json();
} catch (error) {
console.log(`${error.name}: ${error.message}`);
}
server.close();Konsolda:
200 true application/json
[ { Ccy: 'USD', Rate: '11903.15' } ]
404 false {"xato":"topilmadi"}
SyntaxError: Unexpected token '<', "<h1>Xizmat"... is not valid JSONUch saboq:
- 404 — xato emas.
fetchfaqat javob kelmasa xato tashlaydi. 404, 500 — "javob keldi",ok: falsebilan.res.ok(status 200–299) ni o'zingiz tekshirasiz. res.json()— taxmin emas. Server HTML qaytarsa (masalan "xizmat ishlamayapti" sahifasi),SyntaxErrorchiqadi: "<belgisi kutilmagan,<h1>Xizmat… JSON emas".- Tana (body) bir marta o'qiladi:
json()dan keyintext()chaqirsangiz — xato (Response darsi).
valyuta ning birSorov funksiyasi (qayta urinish darsida yozilgan) aynan shu tartibda ishlaydi: avval status (>= 500 — vaqtinchalik xato, qayta urinish; boshqa !ok — oddiy xato), keyin text() va JSON.parse, keyin royxatniOqi bilan tekshiruv.
2.3 Timeout sukut bo'yicha yo'q
fetch da timeout opsiyasi yo'q. Server javob bermasa, so'rov juda uzoq kutishi mumkin. Yechimni bilasiz — AbortSignal.timeout(ms):
TimeoutError: The operation was aborted due to timeoutBu — 2 soniyada javob beradigan serverga AbortSignal.timeout(300) bilan so'rovimizning natijasi. Xato nomi TimeoutError — foydalanuvchi bekor qilganda esa AbortError. valyuta ikkalasini farqlaydi: timeout — qayta urinish, Ctrl+C — darhol to'xtash (timers darsi).
Tekshirib ko'ring:
const data = await (await fetch(url)).json();— bu qatorda nechta tuzoq bor?
Javob
Uchta. (1) Timeout yo'q — server javob bermasa, osilib qolishi mumkin. (2) res.ok tekshirilmagan — 500 javobining tanasi ham JSON sifatida o'qiladi yoki SyntaxError beradi. (3) JSON tuzilmasi tekshirilmagan — data ning shakli siz kutgandek ekaniga kafolat yo'q (valyuta da royxatniOqi).
3. fetch failed: asl sababni o'qish
Tarmoq darajasidagi har qanday xato bir xil ko'rinadi: TypeError: fetch failed. Bu xabar foydasiz. Asl sabab error.cause da (Error obyekti darsi):
import { createServer } from "node:http";
// bo'sh portni topish: ochamiz va darhol yopamiz
const tmp = createServer();
await new Promise((resolve) => tmp.listen(0, "127.0.0.1", resolve));
const freePort = tmp.address().port;
tmp.close();
const urls = [`http://127.0.0.1:${freePort}/`, "http://127.0.0.1:9/"];
for (const url of urls) {
try {
await fetch(url);
} catch (error) {
const cause = error.cause?.code ?? error.cause?.message;
console.log(`${error.name}: ${error.message} ← ${cause}`);
}
}Konsolda:
TypeError: fetch failed ← ECONNREFUSED
TypeError: fetch failed ← bad portBirinchi qator — portda hech kim tinglamayapti, operatsion tizim ulanishni rad etdi (ECONNREFUSED, "ulanish rad etildi"). Ikkinchisini net, dns va tls darsida ko'rgandik: 9-port ochiq yoki yopiqligi muhim emas — fetch unga umuman bormaydi. Fetch standartida "yomon portlar" ro'yxati bor (9, 25 — pochta, 6000 — X11 va boshqalar): brauzer ham, Node ham ularga so'rov yubormaydi. error.cause da code ham yo'q, faqat bad port matni.
Uchinchi tur — DNS. Kanonda http://yoq.invalid/ (.invalid — hech qachon mavjud bo'lmaydigan domen):
fetch failed ← getaddrinfo ENOTFOUND yoq.invalid"yoq.invalid manzili topilmadi" — DNS darsidagi lookup xatosi.
valyuta uchun eslatma. net darsida ko'rganimizdek, valyuta testlari "API ishlamayapti" holatini http://127.0.0.1:9/ bilan sinaydi — bu "ulanish rad etildi" emas, bloklangan port. Test baribir to'g'ri (ikkalasi ham tarmoq xatosi), lekin boshqa sabab bilan o'tayotgan edi. Zanjirni to'liq chiqarish — stack trace va error.cause darsi mavzusi.
Diqqat: Foydalanuvchiga faqat
fetch failedni ko'rsatmang — u hech narsa demaydi. Kamidaerror.causeni qo'shing.valyutashunday chiqaradi:CBU API: tarmoq xatosi ← fetch failed ← connect ECONNREFUSED 127.0.0.1:59999.
4. Keep-alive va ulanishlar hovuzi
4.1 Har so'rov — yangi ulanishmi?
HTTP so'rovdan oldin TCP ulanish ochiladi, HTTPS bo'lsa yana TLS kelishuvi (HTTPS darsi). Bu — bir necha yo'l-borish. Keep-alive — javobdan keyin ulanishni yopmay, keyingi so'rov uchun saqlab qo'yish.
undici buni sukut bo'yicha qiladi. Biz lokal serverda tekshirdik: server har so'rovning soketini (ulanishini) sanaydi. 20 ta ketma-ket so'rov, uch marta. Har qatorda "ulanish" sonini "so'rov" soni bilan solishtiring:
sukut bo'yicha: so'rov 20, ulanish 2
server "connection: close": so'rov 20, ulanish 20Sukut bo'yicha 20 so'rovga atigi 2 ulanish ketdi (uch o'lchovda ham) — qolganlari qayta ishlatildi. Server har javobga connection: close qo'shganda — har so'rovga yangi ulanish.
Halol eslatma: vaqt bo'yicha farqni lokal serverda ko'ra olmadik (62–140 ms va 48–80 ms — tebranish katta). 127.0.0.1 da ulanish ochish deyarli bepul, TLS ham yo'q. Haqiqiy internetda har yangi HTTPS ulanish TCP va TLS kelishuvi uchun bir necha yo'l-borishni oladi — keep-alive shu yerda vaqt tejaydi. Buni biz o'lchamadik.
4.2 Parallel so'rovlar va hovuz
Ketma-ket emas, bir vaqtda 20 ta so'rov yuborsak-chi?
global fetch, 20 parallel: ulanish 20
undici fetch + Agent({ connections: 2 }): ulanish 2Sukut bo'yicha har parallel so'rovga alohida ulanish ochildi. Bitta serverga 20, 200, 2000 ulanish — server uchun og'ir, ba'zi API'lar esa buni hujum deb bloklaydi. Ulanishlar hovuzi (connection pool) — bitta manzil uchun ulanishlar sonini cheklash: qolgan so'rovlar navbatda kutadi. Ikkinchi qatorda 20 so'rov 2 ta ulanish orqali o'tdi.
flowchart LR
R["20 ta so'rov"] --> Q["navbat"]
Q --> P["Pool<br/>connections: 2"]
P --> C1["ulanish 1<br/>(keep-alive)"]
P --> C2["ulanish 2<br/>(keep-alive)"]
C1 --> S["cbu.uz"]
C2 --> SChapdagi 20 so'rov navbatga tushadi, o'ngda esa faqat ikkita doimiy ulanish ishlaydi.
4.3 undici: Agent, Pool, dispatcher
Hovuzni sozlash uchun npm'dagi undici paketi kerak (Node ichidagi undici import qilinmaydi). 2026-10-23 holatiga npm'da undici 8.12.3, Node 24 ichidagisi esa 7.29.1.
| Klass | Nima |
|---|---|
Client |
Bitta manzilga bitta ulanish |
Pool |
Bitta manzilga bir nechta ulanish (connections) |
Agent |
Har manzil uchun o'z Pool i — umumiy "taksi parki" |
dispatcher |
fetch opsiyasi: so'rovni qaysi Agent yoki Pool yuborsin |
import { Agent, fetch } from "undici"; // npm i undici
const agent = new Agent({
connections: 2, // har manzilga ko'pi bilan 2 ulanish
keepAliveTimeout: 10_000, // bo'sh ulanishni 10 s saqlash
});
const API = "https://cbu.uz/uz/arkhiv-kursov-valyut/json/";
const res = await fetch(API, {
dispatcher: agent,
});
await agent.close(); // dastur oxiridaBiz topgan tuzoq. import { Agent } from "undici" — npm'dagi 8-versiya. Uni Node'ning o'rnatilgan fetch iga bersak:
import { Agent } from "undici"; // 8.12.3
await fetch(url, { dispatcher: new Agent() }); // global fetchTypeError: fetch failed
[cause]: InvalidArgumentError: invalid onRequestStart method
code: 'UND_ERR_INVALID_ARG'Sabab — ikki xil undici. Global fetch 7.29.1 "tilida" gapiradi, Agent esa 8.12.3. Ichki interfeys major versiyada o'zgargan ("onRequestStart metodi noto'g'ri"). Bir sinovda bu xato ushlanmay qolib, butun jarayonni yiqitdi. Qoida: npm'dagi Agent ni o'sha paketning fetch i bilan ishlating (import { Agent, fetch } from "undici"). Biz shunday qilganda hovuz to'g'ri ishladi (yuqoridagi "ulanish 2").
setGlobalDispatcher(agent) — butun dastur uchun sukut Agent'ni almashtiradi. Biz undici'ning o'z fetch i bilan sinadik: connections: 1 bilan 10 parallel so'rov — 1 ulanish.
4.4 Narxi va valyuta
undici paketi — 1 paket, 2.1 MB. valyuta CBU'ga ketma-ket so'rov yuboradi (tarixda — har kun bittadan, 100 ms tanaffus bilan), parallel emas. Sukut keep-alive yetadi — undici o'rnatilmadi, prod bog'liqlik 0 qoldi.
Proksi haqida bir gap: korporativ tarmoqda HTTP_PROXY kerak bo'lsa, Node 24 da --use-env-proxy bayrog'i bor (node --help ga ko'ra HTTP_PROXY, HTTPS_PROXY va NO_PROXY ni o'qiydi). Biz uni sinamadik.
Tekshirib ko'ring: Skriptingiz 500 ta mahsulot rasmini bitta serverdan
Promise.allbilan yuklaydi. Server 50 dan keyin ulanishlarni uzyapti. Sabab nima bo'lishi mumkin va qanday tuzatasiz?
Javob
Sukut bo'yicha har parallel so'rov alohida ulanish ochadi — 500 ta bir vaqtda. Server (yoki uning oldidagi himoya) bunchalik ulanishni qabul qilmaydi. Tuzatish: (1) undici Agent({ connections: 10 }) va undici'ning fetch i; yoki (2) kutubxonasiz — parallellikni o'zingiz cheklash (bir vaqtda 10 ta, 3-mashqdagidek).
5. axios, ky, ofetch — kerakmi?
Biz to'rt paketni alohida papkalarga o'rnatdik (2026-10-23):
| Paket | Paketlar | Hajm | Nima qo'shadi |
|---|---|---|---|
| axios 1.20.0 | 27 | 2.6 MB | o'z HTTP qatlami, interceptor'lar, 4xx/5xx da xato |
| ky 2.2.0 | 1 | 0.6 MB | fetch ustida: qayta urinish, timeout, HTTPError |
| ofetch 1.5.1 | 4 | 0.9 MB | fetch ustida: avtomatik JSON, qayta urinish |
| undici 8.12.3 | 1 | 2.1 MB | hovuz, Agent, MockAgent, proksi |
Import narxini ham o'lchadik (15 marta mediana). Lekin mashina band bo'lgani uchun ikki o'lchov katta farq qildi: axios +176…+268 ms, ky +134…+211, ofetch +96…+141, undici +218…+255 ms. Bu aniq raqam emas, tartib muhim: har biri valyuta ning butun ishga tushishiga (≈100 ms) yaqin yoki undan ko'p vaqt qo'shadi.
Qachon nima:
fetchyetadi — bir nechta API chaqiruvi, o'zqaytaUrinvaAbortSignal.timeoutingiz bor (valyuta).- ky yoki ofetch — ko'p API chaqiruvi bor, qayta urinish va xato klasslarini qayta yozishni xohlamaysiz. Ikkalasi ham
fetchustida, brauzerda ham ishlaydi. - axios — mavjud loyiha uni ishlatadi yoki interceptor'lar kerak (masalan, token yangilash). Yangi Node loyihasida majburiy emas.
- undici — hovuz, yuqori yuk, testda so'rovlarni soxtalashtirish (
MockAgent).
6. CLI qadami: User-Agent (holat 46, 1-qism)
Holat 46 uch darsga bo'lingan: bugun fetch qismi, keyin debug va stack trace, error.cause. Hali commit qilmang — commit uchinchi darsda.
Sukut bo'yicha har so'rovda User-Agent: node boradi — biz sinadik, lokal server aynan node ni ko'rdi. CBU loglarida bu "kimdir, nimadir". Odob bo'yicha (va scraping darsidagi qoidaga ko'ra) dastur o'zini tanishtirishi kerak. src/manba.ts dagi o'zgarish (kanon, qisqartirilgan):
+import paket from "../package.json" with { type: "json" };
+
+// CBU loglarida kim so'rov yuborayotgani ko'rinsin
+export const USER_AGENT =
+ `valyuta/${paket.version} (Node.js ${process.versions.node})`;
…
- javob = await fetch(url, { signal: … });
+ javob = await fetch(url, {
+ signal: …,
+ headers: { "user-agent": USER_AGENT },
+ });Natija: valyuta/0.2.0 (Node.js 24.21.0). Kanon testi buni lokal server bilan tekshiradi: server kelgan sarlavhani yozib oladi, test uni ^valyuta\/\d+\.\d+\.\d+ \(Node\.js 24\. naqshi bilan solishtiradi.
Holat 46 dagi ikkinchi fetch o'zgarishi — Ctrl+C. bin.ts AbortController yaratadi va uning signal ini main() orqali fetch gacha uzatadi. fetch ga ikki signal birlashib boradi: AbortSignal.any([signal, AbortSignal.timeout(kutishMs)]) — foydalanuvchi to'xtatsa ham, vaqt tugasa ham so'rov uziladi. Tafsiloti — stack trace va error.cause darsida. Halol eslatma: haqiqiy terminalda Ctrl+C bosish kanonda sinalmagan — test uni 100 ms da bekor qilinadigan signal bilan modellaydi.
7. Ko'p uchraydigan xatolar
| Belgi | Sabab | Davosi |
|---|---|---|
| 500 javobi "muvaffaqiyatli" o'tdi | fetch faqat tarmoq xatosida tashlaydi |
if (!res.ok) |
SyntaxError: Unexpected token '<' |
JSON o'rniga HTML keldi | Avval res.ok va content-type |
| So'rov osilib qoldi | Timeout yo'q | AbortSignal.timeout(ms) |
TypeError: fetch failed — sabab noma'lum |
Asl xato cause da |
error.cause zanjirini chiqaring |
fetch failed ← bad port |
Fetch bloklagan port (9, 25 …) | Boshqa port |
invalid onRequestStart method |
npm undici Agent + o'rnatilgan fetch |
undici'ning o'z fetch i |
| Tana ikkinchi marta o'qilmayapti | Body bir martalik | Bir marta o'qing yoki res.clone() |
| Server ko'p ulanishdan uzadi | Cheksiz parallel so'rov | Hovuz yoki parallellik chegarasi |
8. Mashqlar
Yechimlar kurs/mashqlar/24/42-fetch-undici/ da.
1-mashq (oson): to'ldiring
fetch404 javobida xato tashlaydimi?- Javob 200–299 ekanini bildiruvchi xususiyat —
res. - Tarmoq xatosining asl sababi —
error. - Node 24 dagi
fetchqaysi kutubxona ustida qurilgan? - Bitta manzilga ulanishlar sonini cheklaydigan undici opsiyasi —
Yechim
- yo'q — javob keldi,
ok: false. - ok — 200–299 da
true. - cause —
fetch failedichidaECONNREFUSED,ENOTFOUND,bad port. - undici —
process.versions.undici. - connections —
PoolvaAgentopsiyasi.
2-mashq (o'rta): getJson
getJson(url, timeoutMs) funksiyasini yozing. U timeout bilan so'rasin. !res.ok bo'lsa — Error("HTTP <status>"). Tarmoq xatosida — Error("Tarmoq: <cause.code yoki cause.message>"), cause sifatida asl xato bilan. Timeout bo'lsa — Error("<ms> ms ichida javob yo'q"). Lokal server bilan to'rt holatni sinang (blok — Node uchun).
Yechim
import { createServer } from "node:http";
async function getJson(url, timeoutMs) {
let res;
try {
const signal = AbortSignal.timeout(timeoutMs);
res = await fetch(url, { signal });
} catch (error) {
if (error.name === "TimeoutError") {
throw new Error(`${timeoutMs} ms ichida javob yo'q`);
}
const why = error.cause?.code ?? error.cause?.message;
throw new Error(`Tarmoq: ${why}`, { cause: error });
}
if (!res.ok) throw new Error(`HTTP ${res.status}`);
return res.json();
}
const server = createServer((req, res) => {
if (req.url === "/sekin") {
return setTimeout(() => res.end("{}"), 1000);
}
res.statusCode = req.url === "/yoq" ? 404 : 200;
res.end('{"USD":11903.15}');
});
await new Promise((ok) => server.listen(0, "127.0.0.1", ok));
const base = `http://127.0.0.1:${server.address().port}`;
const urls = [`${base}/`, `${base}/yoq`, `${base}/sekin`];
for (const url of [...urls, "http://127.0.0.1:9/"]) {
try {
console.log(await getJson(url, 200));
} catch (error) {
console.log(error.message);
}
}
server.closeAllConnections();
server.close();Konsolda:
{ USD: 11903.15 }
HTTP 404
200 ms ichida javob yo'q
Tarmoq: bad portserver.closeAllConnections() — sekin javob kutayotgan ulanishni ham yopadi; aks holda close() uni 1 s kutardi.
3-mashq (qiyin): parallellik chegarasi
Kutubxonasiz hovuz modeli yozing: mapLimit(items, limit, fn). U items ning har biri uchun fn ni chaqirsin, lekin bir vaqtda ko'pi bilan limit ta ishlasin; natijalar items tartibida qaytsin. Soxta fetch (taymer bilan) va "bir vaqtda nechta ishladi" hisoblagichi bilan sinang. Bu toza JS — saytdagi «Ishga tushir» bilan ham ishlaydi.
Yechim
async function mapLimit(items, limit, fn) {
const results = new Array(items.length);
let next = 0;
async function worker() {
while (next < items.length) {
// await dan oldin — ikki ishchi bir xil i ni olmaydi
const i = next++;
results[i] = await fn(items[i], i);
}
}
const count = Math.min(limit, items.length);
await Promise.all(Array.from({ length: count }, worker));
return results;
}
let active = 0;
let maxActive = 0;
const fakeFetch = (day, i) =>
new Promise((resolve) => {
active++;
maxActive = Math.max(maxActive, active);
setTimeout(() => {
active--;
resolve(`${day}: ${11900 + i}`);
}, 20 + (i % 3) * 10);
});
const days = ["10-20", "10-21", "10-22", "10-23", "10-24", "10-25"];
const results = await mapLimit(days, 2, fakeFetch);
console.log(results.slice(0, 3).join(" | "));
console.log(results.slice(3).join(" | "));
console.log("bir vaqtda ko'pi bilan:", maxActive);Konsolda:
10-20: 11900 | 10-21: 11901 | 10-22: 11902
10-23: 11903 | 10-24: 11904 | 10-25: 11905
bir vaqtda ko'pi bilan: 2Har ishchi navbatdan keyingi elementni oladi — Pool ning connections i shunday ishlaydi. next++ await dan oldin bo'lgani muhim: JS bir oqimli, shuning uchun ikki ishchi bir indeksni ololmaydi (event loop).
4-mashq: CLI qadami
src/manba.ts ga USER_AGENT konstantasini qo'shing va fetch ga user-agent sarlavhasini bering. Test yozing: node:http lokal server kelgan sarlavhani saqlaydi; apidanOl(lokalUrl) dan keyin assert.match(ua, /^valyuta\/\d+\.\d+\.\d+ \(Node\.js 24\./). npm test — yashil. Commit qilmang.
Yechim
Namuna — «CLI qadami» bo'limidagi diff. Test — kanondagi "xato zanjiri (cause) va User-Agent" testining birinchi yarmi: createServer((q, r) => { ua = q.headers["user-agent"] ?? ""; r.end(FIXTURE_MATN); }), listen(0, "127.0.0.1"), so'rovdan keyin close(). package.json ni import … with { type: "json" } bilan o'qish uchun tsconfig da resolveJsonModule bor (holat 20 dan).
9. Real ishda
- Backend'da tashqi API — to'lov tizimlari, SMS, Telegram Bot API — hammasi
fetchyoki axios bilan. Timeout, qayta urinish vacauseni log'ga yozish — har birida majburiy. - Yuqori yuk — bitta xizmatga sekundiga yuzlab so'rov: undici
Agentbilan hovuz, keep-alive,connectionschegarasi. - Testlar — tashqi API'ni soxtalashtirish: lokal
node:httpserver (valyutatestlari) yoki undiciMockAgent. - Intervyu savollari: "fetch 404 da xato tashlaydimi?", "fetch'ga timeout qanday qo'shiladi?", "keep-alive nima va nega kerak?", "axios va fetch farqi?".
Xulosa
- Node 24
fetch— brauzer API'si, ichida undici 7.29.1; CORS, cookie va kesh yo'q,User-Agent: node. res.okni tekshiring, timeout'niAbortSignal.timeoutbilan bering, JSON shaklini tekshiring.- Tarmoq xatosi — doim
TypeError: fetch failed; sababerror.causeda (ECONNREFUSED,ENOTFOUND,bad port). - Keep-alive sukut bo'yicha (20 so'rov — 2 ulanish); parallel so'rovlar cheklanmaydi — hovuz uchun undici
Agent({ connections })va undici'ning o'zfetchi. - axios, ky, ofetch — qulaylik, lekin har biri 0.6–2.6 MB va sezilarli import vaqti;
valyutagafetchyetadi.
Keyingi dars: Node'ning yangi o'rnatilgan imkoniyatlari — node:sqlite, WebSocket, URLPattern, crypto.argon2, zstd va boshqa "paketsiz" imkoniyatlar.
Manbalar
- Node.js 24 hujjati — Globals,
fetch: https://nodejs.org/docs/latest-v24.x/api/globals.html - undici hujjati — Agent, Pool, Dispatcher,
setGlobalDispatcher: https://undici.nodejs.org (npm: 8.12.3, 2026-10-23) - Fetch Standard — port blocking ("bad port"): https://fetch.spec.whatwg.org/#port-blocking
- axios 1.20.0, ky 2.2.0, ofetch 1.5.1 — npm reestri, 2026-10-23.
- Kanon:
valyutaholat 46 (USER_AGENT,AbortSignal.any),fetch failedzanjirlari (ECONNREFUSED, bad port, ENOTFOUND). Keep-alive, hovuz, undici 8 aralashuv xatosi, paket o'lchovlari — biz ishga tushirdik (Node 24.21.0, lokalnode:httpserver, Windows 11).
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!