IlmHamroh
JavaScript Full-stack/24-qism. Node.js42/55-dars17 daqiqa
Mundarija (23)

Node.js fetch va undici: timeout, xatolar, keep-alive va ulanishlar hovuzi

Qisqacha: Node 24 da fetch global — brauzerdagi bilan bir xil API, ichida undici kutubxonasi (7.29.1). Uch narsani bilish shart: fetch 404/500 da xato tashlamaydi (res.ok ni tekshirasiz); timeout sukut bo'yicha yo'q (AbortSignal.timeout); tarmoq xatosi har doim TypeError: fetch failed, asl sabab esa error.cause da. Ulanishlarni undici o'zi qayta ishlatadi (keep-alive). Hovuzni boshqarish uchun npm'dagi undici paketining Agent i kerak — lekin u o'z fetch i bilan ishlatiladi. Biz sinadik: npm'dagi undici 8 Agent ini o'rnatilgan fetch ga bersak, invalid onRequestStart method xatosi chiqadi.

Bu darsda

  • Node'dagi fetch brauzerdagidan nimasi bilan farq qilishini bilasiz.
  • res.ok, res.json(), AbortSignal.timeout bilan xavfsiz so'rov yozasiz.
  • fetch failed ichidagi asl sababni (ECONNREFUSED, ENOTFOUND, bad port) o'qiy olasiz.
  • Keep-alive va ulanishlar hovuzi (pool) nima ekanini o'lchov bilan ko'rasiz; undici Agent va dispatcher ni ishlatasiz.
  • axios, ky, ofetch qachon kerakligini aniq ayta olasiz; valyuta ga 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:

js
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:

text
200 true application/json
[ { Ccy: 'USD', Rate: '11903.15' } ]
404 false {"xato":"topilmadi"}
SyntaxError: Unexpected token '<', "<h1>Xizmat"... is not valid JSON

Uch saboq:

  1. 404 — xato emas. fetch faqat javob kelmasa xato tashlaydi. 404, 500 — "javob keldi", ok: false bilan. res.ok (status 200–299) ni o'zingiz tekshirasiz.
  2. res.json() — taxmin emas. Server HTML qaytarsa (masalan "xizmat ishlamayapti" sahifasi), SyntaxError chiqadi: "< belgisi kutilmagan, <h1>Xizmat… JSON emas".
  3. Tana (body) bir marta o'qiladi: json() dan keyin text() 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):

text
TimeoutError: The operation was aborted due to timeout

Bu — 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):

js
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:

text
TypeError: fetch failed ← ECONNREFUSED
TypeError: fetch failed ← bad port

Birinchi 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):

text
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 failed ni ko'rsatmang — u hech narsa demaydi. Kamida error.cause ni qo'shing. valyuta shunday 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:

text
sukut bo'yicha:              so'rov 20, ulanish 2
server "connection: close":  so'rov 20, ulanish 20

Sukut 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?

text
global fetch, 20 parallel:                 ulanish 20
undici fetch + Agent({ connections: 2 }):  ulanish 2

Sukut 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 --> S

Chapdagi 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
js
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 oxirida

Biz topgan tuzoq. import { Agent } from "undici" — npm'dagi 8-versiya. Uni Node'ning o'rnatilgan fetch iga bersak:

js
import { Agent } from "undici"; // 8.12.3

await fetch(url, { dispatcher: new Agent() }); // global fetch
text
TypeError: 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.all bilan 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:

  • fetch yetadi — bir nechta API chaqiruvi, o'z qaytaUrin va AbortSignal.timeout ingiz bor (valyuta).
  • ky yoki ofetch — ko'p API chaqiruvi bor, qayta urinish va xato klasslarini qayta yozishni xohlamaysiz. Ikkalasi ham fetch ustida, 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):

diff
+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

  • fetch 404 javobida xato tashlaydimi?
  • Javob 200–299 ekanini bildiruvchi xususiyat — res.
  • Tarmoq xatosining asl sababi — error.
  • Node 24 dagi fetch qaysi kutubxona ustida qurilgan?
  • Bitta manzilga ulanishlar sonini cheklaydigan undici opsiyasi —
Yechim
  • yo'q — javob keldi, ok: false.
  • ok — 200–299 da true.
  • cause — fetch failed ichida ECONNREFUSED, ENOTFOUND, bad port.
  • undici — process.versions.undici.
  • connections — Pool va Agent opsiyasi.

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
js
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:

text
{ USD: 11903.15 }
HTTP 404
200 ms ichida javob yo'q
Tarmoq: bad port

server.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
js
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:

text
10-20: 11900 | 10-21: 11901 | 10-22: 11902
10-23: 11903 | 10-24: 11904 | 10-25: 11905
bir vaqtda ko'pi bilan: 2

Har 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 fetch yoki axios bilan. Timeout, qayta urinish va cause ni log'ga yozish — har birida majburiy.
  • Yuqori yuk — bitta xizmatga sekundiga yuzlab so'rov: undici Agent bilan hovuz, keep-alive, connections chegarasi.
  • Testlar — tashqi API'ni soxtalashtirish: lokal node:http server (valyuta testlari) yoki undici MockAgent.
  • 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.ok ni tekshiring, timeout'ni AbortSignal.timeout bilan bering, JSON shaklini tekshiring.
  • Tarmoq xatosi — doim TypeError: fetch failed; sabab error.cause da (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'z fetch i.
  • axios, ky, ofetch — qulaylik, lekin har biri 0.6–2.6 MB va sezilarli import vaqti; valyuta ga fetch yetadi.

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: valyuta holat 46 (USER_AGENT, AbortSignal.any), fetch failed zanjirlari (ECONNREFUSED, bad port, ENOTFOUND). Keep-alive, hovuz, undici 8 aralashuv xatosi, paket o'lchovlari — biz ishga tushirdik (Node 24.21.0, lokal node:http server, Windows 11).
Ulashish:Telegram'da

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
Node.js fetch va undici: timeout, xatolar, keep-alive va ulanishlar hovuzi — IlmHamroh