5.1-bob: Node.js kirish — runtime, event loop (chuqur), V8
5-QISM — Node.js Backend · 1-mavzu
1. Kirish va motivatsiya
Mana, kitobning eng katta amaliy qismlaridan biriga — backend (server) dasturlashga keldik. 0.7-bobda Node.js'ni o'rnatdik, 2-QISMda JavaScript'ni chuqur o'rgandik, 0.4-bobda HTTP va server tushunchasini ko'rdik. Endi hammasi birlashadi: JavaScript bilan server yozamiz.
Node.js — JavaScript'ni brauzerdan tashqarida, serverda ishlatadigan muhit (runtime). U tufayli siz bitta til — JavaScript — bilan butun stackni (frontend + backend) yozasiz. Bu — bu kitobning butun mantig'i va Node.js'ning butun dunyoni zabt etgan sababi.
Lekin 5.1-bob shunchaki "Node nima" emas. Bu — Node.js'ning yuragini — event loop va non-blocking I/O mexanizmini — chuqur ochadigan bob. Mana shu mexanizm Node.js'ni qanday qilib bitta thread bilan minglab foydalanuvchiga xizmat ko'rsatishini tushuntiradi. Buni tushunmasdan, Node'da "sehr" bo'lib qoladi; tushunsangiz — siz performance, scalability va "nega serverim qotib qoldi?" muammolarini hal qila olasiz.
O'xshatish (event loop): bitta ofitsiantli restoran. Oddiy ofitsiant bir stolda turib, ovqat pishishini kutadi (blocking) — boshqa stollar och qoladi. Aqlli ofitsiant (Node) esa buyurtmani oshxonaga beradi va kutmasdan boshqa stollarga xizmat qiladi; ovqat tayyor bo'lganda (event), uni olib keladi (callback). Bitta ofitsiant — yuzlab stol! Bu — non-blocking I/O.
Nega bu bob nihoyatda muhim?
- Butun 5-QISM (23 bob) va NestJS (8-QISM) shu poydevorga quriladi.
- Performance/scalability — "nega Node tez?", "nega serverim sekin?" — javobi shu yerda.
- Intervyu — event loop, process.nextTick vs setImmediate — backend intervyularning klassikasi.
- 0.1 (CPU/thread), 0.2 (process/OS), 0.5 (V8/event loop kirishi), 2.11 (async) — hammasi bu yerda birlashadi va chuqurlashadi.
2. Nazariya — chuqur tushuntirish
2.1. Node.js aslida nima? (3 ta noto'g'ri tushuncha)
Avvalo, Node.js nima emasligini aniqlaylik (eng ko'p chalkashlik):
- Node.js — dasturlash tili emas (til — JavaScript).
- Node.js — framework emas (Express — framework, Node emas).
- Node.js — runtime (ishga tushirish muhiti): JavaScript kodni brauzerdan tashqarida ishlatadigan dastur.
Ya'ni: JavaScript — til; V8 — uni mashina kodiga aylantiradigan engine 0.5-bob; Node.js — V8'ni o'rab, unga server qobiliyatlari (fayl, tarmoq, OS) qo'shgan muhit.
O'xshatish: JavaScript — suv. Brauzer — bir idish (shisha). Node.js — boshqa idish (chelak). Suv (til) bir xil, lekin idish (muhit) har xil imkoniyat beradi: brauzerda DOM, Node'da fayl/server.
2.2. Node.js arxitekturasi — uch asosiy qism
Node.js — bir necha komponentdan tashkil topgan tizim (nodejs.org/libuv hujjatlariga ko'ra):
┌──────────────────────────────────────────────────┐
│ SIZNING JS KODINGIZ (app.js) │
├──────────────────────────────────────────────────┤
│ Node.js API (fs, http, crypto, path... — 5.3) │
├───────────────────────────┬──────────────────────┤
│ V8 Engine │ libuv (C) │
│ (JS mashina kodi — 0.5) │ (event loop, I/O, │
│ │ thread pool) │
├───────────────────────────┴──────────────────────┤
│ Operatsion tizim (OS — 0.2): fayl, tarmoq │
└──────────────────────────────────────────────────┘- V8 — JavaScript'ni bajaradi (mashina kodiga aylantiradi — 0.5). U faqat JS ni biladi; I/O, tarmoq haqida hech narsa bilmaydi.
- libuv — C tilida yozilgan kutubxona; event loop va asinxron I/O (fayl, tarmoq) shu yerda yashaydi. Node'ning "sehri" — aynan shu.
- Node API — V8 va libuv'ni JavaScript'ga bog'laydigan ko'prik (
fs,http,crypto— 5.3).
Muhim: event loop V8'da emas, libuv'da. V8 — sinxron (faqat JS bajaradi); butun asinxronlik (event loop, I/O orkestrlash) — libuv'ning ishi (libuv docs).
2.3. V8 — JavaScript'ni bajaruvchi (0.5 chuqurroq)
V8 (0.5-bobda ko'rgandik) — Google'ning JS engine'i: JavaScript'ni mashina kodiga kompilyatsiya qiladi (Parser AST Ignition bytecode TurboFan JIT — 0.5). Node.js xuddi shu V8'ni ishlatadi (brauzer Chrome bilan bir xil).
V8'ning muhim xususiyati — u fundamental sinxron va bitta thread'da ishlaydi (0.1, 0.5). U I/O, tarmoq, thread haqida hech narsa bilmaydi. Demak, agar Node faqat V8'dan iborat bo'lsa — har fayl o'qishda butun dastur qotib qolardi. Aynan shu yerda libuv kerak bo'ladi.
2.4. libuv — I/O orkestratori va event loop uyi
libuv — C tilida yozilgan, platformalararo kutubxona (dastlab Node uchun yaratilgan — libuv docs). U Node'da butun asinxron ishni boshqaradi: fayl tizimi 0.2-bob, tarmoq 0.4-bob, DNS, child process, va eng muhimi — event loop.
libuv ikki mexanizmdan foydalanadi:
- OS'ning native asinxron API'lari (tarmoq uchun): Linux —
epoll, macOS —kqueue, Windows —IOCP. Bular OS yadrosi darajasida 0.2-bob ishlaydi — juda samarali. - Thread pool (fayl/CPU uchun): native async API yo'q amallar uchun 2.10-bob.
2.5. Single-threaded JS + non-blocking I/O — Node'ning yuragi
Mana eng muhim g'oya. Node.js'da sizning JS kodingiz bitta thread'da ishlaydi (0.1, 0.2: single-threaded). "Bitta thread bilan qanday minglab foydalanuvchiga xizmat qiladi?" — javob non-blocking I/Oda.
ANANAVIY SERVER (PHP, har so'rovga thread):
1000 foydalanuvchi 1000 OS thread ko'p RAM, kontekst almashinuvi 0.2-bob
NODE.JS (bitta thread + event loop):
1000 foydalanuvchi bitta thread, har so'rov "event" sifatida ro'yxatga olinadi
I/O OS'ga/thread pool'ga topshiriladi kutmaydi keyingisini xizmat qiladi
I/O tayyor bo'lganda callback ishlaydiNega bu inqilobiy: har HTTP so'rovga yangi OS thread ochilmaydi (qimmat — 0.2). So'rov event sifatida ro'yxatga olinadi; I/O (DB, fayl, tarmoq) kutilmaydi — boshqa so'rovlar xizmat qilinadi; natija tayyor bo'lganda callback chaqiriladi. Shuning uchun Node 10,000+ bir vaqtdagi ulanishni 10,000 thread'siz uddalaydi. Bu — I/O-og'ir (ko'p so'rov) ilovalar uchun ideal.
2.6. Blocking vs non-blocking (sync vs async)
Node API'larining ko'pi ikki versiyada: blocking (sinxron) va non-blocking (asinxron — 2.11):
BLOCKING (sync): natija kelguncha THREAD TO'XTAYDI (butun server kutadi!)
const data = fs.readFileSync("katta.txt"); // server qotadi
NON-BLOCKING (async): topshiriladi, thread DAVOM ETADI, callback keyin
fs.readFile("katta.txt", (err, data) => {...}); // server javob beradiOltin qoida: server kodida hech qachon blocking (
...Sync) API ishlatmang (skriptlarda mayli). BittareadFileSyncbutun serverni — barcha foydalanuvchilarni — to'xtatadi 2.5-bob. Doim async (callback / Promise / async-await — 2.11).
2.7. Event loop — to'liq mexanizm (6 faza)
Event loop — libuv'ning yuragi: asinxron callback'larni qachon va qaysi tartibda ishga tushirishni boshqaradigan cheksiz tsikl. U fazalardan iborat; har fazada o'ziga tegishli callback'lar navbati (FIFO — 3.4) bajariladi (nodejs.org/libuv):
┌───────────────────────────┐
┌─▶│ 1. timers │ setTimeout, setInterval callback'lari
│ ├───────────────────────────┤
│ │ 2. pending callbacks │ ba'zi tizim I/O callback'lari (kechiktirilgan)
│ ├───────────────────────────┤
│ │ 3. idle, prepare │ ichki (Node o'zi ishlatadi)
│ ├───────────────────────────┤
│ │ 4. poll │ ◀── ASOSIY: I/O callback'lar (fayl, tarmoq);
│ │ │ yangi I/O eventlarni kutadi/oladi
│ ├───────────────────────────┤
│ │ 5. check │ setImmediate callback'lari
│ ├───────────────────────────┤
│ │ 6. close callbacks │ 'close' eventlari (socket.on('close'))
│ └───────────────────────────┘
└────── (har fazadan keyin: microtask navbatlari — 2.8)| Faza | Nima bajaradi |
|---|---|
| timers | setTimeout/setInterval — vaqti kelgan callback'lar |
| pending callbacks | kechiktirilgan tizim I/O callback'lari |
| idle, prepare | ichki (Node o'zi) |
| poll | eng muhim — I/O callback'lar; yangi I/O kutadi/oladi |
| check | setImmediate callback'lari |
| close callbacks | close eventlari (resurs yopilishi) |
poll fazasi — yurak: event loop vaqtining ko'rini shu yerda o'tkazadi. I/O callback'larni bajaradi; agar ish yo'q bo'lsa, yangi I/O eventlarni kutadi (yoki timer/immediate bo'lsa, o'tadi). Tarmoq/fayl natijalari shu yerda "qaytadi".
2.8. Microtask navbatlari — fazalar orasida
Event loop fazalari libuv'da. Lekin yana ikki microtask navbati bor — ular libuv'da emas, Node runtime'da, va ular har faza orasida, fazalardan oldin bajariladi (nodejs.org):
process.nextTick()navbati — eng yuqori ustuvorlik.- Promise (microtask) navbati —
.then/catch/finally,await2.11-bob.
Har callback'dan keyin (yoki faza tugashi bilan):
1. nextTick navbati TO'LIQ bo'shatiladi (eng oldin)
2. Promise navbati TO'LIQ bo'shatiladi
3. keyin event loop keyingi fazaga o'tadiUstuvorlik tartibi (yodlang): sinxron kod process.nextTick Promise (microtask) timers/I/O/check (macrotask fazalar). Bu — event loop tartibini bashorat qilishning kaliti (Misol 3).
2.9. process.nextTick vs setImmediate vs setTimeout
Uchta "keyinroq bajar" mexanizmi, lekin har xil vaqtda:
| Mexanizm | Qachon ishlaydi |
|---|---|
process.nextTick(cb) |
darrov, joriy amaldan keyin, har fazadan oldin (eng tez) |
Promise.then(cb) |
nextTick'dan keyin (microtask) |
setImmediate(cb) |
check fazasida (poll'dan keyin) |
setTimeout(cb, 0) |
timers fazasida (keyingi tsiklda) |
console.log("1: sinxron");
setTimeout(() => console.log("5: setTimeout"), 0); // timers fazasi
setImmediate(() => console.log("4: setImmediate")); // check fazasi
Promise.resolve().then(() => console.log("3: Promise")); // microtask
process.nextTick(() => console.log("2: nextTick")); // eng oldin
console.log("1.5: sinxron");
// Tartib: 1 1.5 2 3 (4 yoki 5, kontekstga bog'liq)
process.nextTick"ochlik" (starvation) xavfi: u har fazadan oldin to'liq bo'shatiladi. AgarnextTickichida yananextTickqo'shaversa — event loop hech qachon keyingi fazaga o'tmaydi (I/O bloklanadi). Ehtiyot bo'ling (Misol 5).
2.10. Thread pool — libuv'ning yashirin ishchilari
Node "single-threaded" deyilsa-da, libuv'ning thread pool'i bor (default 4 ta thread — libuv docs). JS kodi bitta thread'da, lekin ba'zi og'ir/blocking amallar bu pool'da, parallel (0.1: yadrolar) bajariladi:
Thread pool'ga tushadigan amallar:
- Fayl tizimi (
fs— 5.3) — native async API yo'q, shuning uchun pool. - DNS (
dns.lookup). - Crypto (
crypto.pbkdf2,bcrypt— 5.15) — CPU-og'ir. - Zlib (siqish) — CPU-og'ir.
# Thread pool hajmini o'zgartirish (default 4)
UV_THREADPOOL_SIZE=8 node app.jsMuhim farq 2.11-bob: tarmoq I/O (HTTP, TCP) thread pool'ni ishlatmaydi — u OS'ning native async API'si (epoll/kqueue/IOCP) bilan, asosiy thread'da. Fayl/CPU amallari esa thread pool'da. Shuning uchun Node minglab tarmoq ulanishini 4 thread bilan ham uddalaydi (tarmoq pool'siz).
2.11. Network I/O vs File I/O (nega farq qiladi)
TARMOQ I/O (HTTP, TCP, socket):
OS native async (epoll/kqueue/IOCP) — 0.2
thread pool KERAK EMAS
minglab ulanish, asosiy thread'da samarali
FAYL I/O (fs), DNS, crypto, zlib:
native async API yo'q
libuv THREAD POOL (default 4) — parallel
5 ta og'ir crypto bir vaqtda 4 tasi parallel, 5-chisi kutadiBu farq performance'da muhim: agar ilovang ko'p fayl/crypto ishlatsa, thread pool (4) bottleneck bo'lishi mumkin — UV_THREADPOOL_SIZE ni oshirish kerak 2.10-bob.
2.12. Node global obyektlar va process
Brauzerda window global obyekt edi 0.5-bob; Node'da global (va globalThis). Node'ning eng muhim global obyekti — process (joriy Node process haqida — 0.2):
process.argv // buyruq qatori argumentlari (0.3, 0.4) — ["node", "app.js", ...]
process.env // environment variables 5.8-bob — process.env.PORT
process.cwd() // joriy ish papkasi (0.2)
process.platform // "linux" / "win32" / "darwin" (0.2)
process.pid // process ID (0.2)
process.exit(0) // process'ni to'xtatish (0 — muvaffaqiyat)
process.on("exit", cb)// process tugashida (event — 5.4)
__dirname // joriy fayl papkasi (0.2, 0.7)
__filename // joriy fayl to'liq yo'li2.13. REPL va Node'ni ishga tushirish
node app.js # faylni ishga tushirish (0.7)
node # REPL (interaktiv — har qatorni darrov bajaradi)
node --watch app.js # fayl o'zgarsa qayta ishga tushiradi (nodemon'siz)
node -e "console.log(2+2)" # bir qatorli kodREPL (Read-Eval-Print Loop — 0.3: shell ham REPL) — node deb yozsangiz ochiladi; JS'ni darrov sinab ko'rish uchun (.exit bilan chiqasiz).
2.14. Node vs Brauzer JavaScript (farqlar)
| Brauzer | Node.js | |
|---|---|---|
| Global obyekt | window |
global / globalThis |
| DOM (2.16) | bor | yo'q (server'da sahifa yo'q) |
Fayl tizimi (fs) |
yo'q (xavfsizlik) | bor (5.3) |
| Modul | ESM (0.5) | ESM + CommonJS (2.15) |
process |
yo'q | bor |
| Event loop | brauzer beradi | libuv beradi |
Til (JavaScript) bir xil; muhit (API) har xil.
2.15. CommonJS vs ESM — Node'da ikki modul tizimi
Node'da kodni bo'laklarga (modullarga) ajratishning ikki usuli bor (5.2 da chuqurroq):
- CommonJS (CJS) — Node'ning tarixiy/an'anaviy tizimi.
require()bilan import,module.exportsbilan export. Sinxron yuklanadi; standart kengaytma.js. - ESM (ECMAScript Modules) — JavaScript'ning rasmiy standart tizimi (brauzer ham shuni ishlatadi — 0.5).
import/exportbilan; standart kengaytma.mjs(yokipackage.jsonda"type": "module"— 5.2).
// CommonJS (an'anaviy)
const fs = require("fs"); // import
module.exports = { salom }; // export
// ESM (standart)
import fs from "fs"; // import
export const salom = () => {}; // exportQaysi birini tanlash? Yangi loyihalarda ESM afzal (standart, brauzer bilan bir xil). Lekin ko'p eski paket va misol hali CommonJSda — shuning uchun ikkalasini ham bilish kerak. Bu bobning kod misollarida
require(CommonJS) ishlatiladi, chunki u Node'da konfiguratsiyasiz ishlaydi. Modullarni 5.2-bobda batafsil ochamiz.
3. Sintaksis va ishga tushirish
# Ishga tushirish
node app.js node --watch app.js
# Async API (server'da DOIM shu — 2.6)
fs.readFile(path, cb) # non-blocking
fs.readFileSync(path) # blocking (server'da emas)
# Timing (2.9)
process.nextTick(cb) # eng oldin (microtask'dan ham)
queueMicrotask(cb) # Promise microtask
setImmediate(cb) # check fazasi
setTimeout(cb, ms) # timers fazasi
# Global
process.argv / .env / .exit() __dirname / __filename4. Batafsil kod namunalari
Misol 1 — Birinchi Node dastur va process (2.12)
// app.js — Node muhitini tekshiramiz
console.log("Salom, Node!");
console.log("Versiya:", process.version); // masalan v22.x
console.log("Platforma:", process.platform); // "win32" / "linux" (0.2)
console.log("Joriy papka:", process.cwd()); // (0.2)
console.log("Bu fayl:", __filename); // to'liq yo'l (0.7)
console.log("Argumentlar:", process.argv); // ["node", "app.js", ...]
// Buyruq qatori argumentini olish (0.3, 0.4: misol 4)
const ism = process.argv[2] ?? "Mehmon"; // node app.js Ali "Ali" (2.1)
console.log(`Salom, ${ism}!`);
// Ishga tushirish: node app.js AliMisol 2 — Blocking vs Non-blocking 2.6-bob — server'ning hayot-mamot masalasi
const fs = require("fs"); // core modul (5.3, 2.14: CommonJS)
// BLOCKING — butun thread to'xtaydi (server qotadi!)
console.log("1: boshlandi");
const data = fs.readFileSync("fayl.txt", "utf8"); // KUTADI (2.6)
console.log("2: fayl o'qildi:", data.length, "belgi");
console.log("3: tugadi");
// Tartib: 1 2 3 (lekin 1 va 2 orasida server HECH KIMGA javob bermaydi)
// NON-BLOCKING — thread davom etadi, callback keyin
console.log("A: boshlandi");
fs.readFile("fayl.txt", "utf8", (err, data) => { // topshiriladi (2.6)
if (err) return console.error("Xato:", err.message); // (2.12: error handling)
console.log("C: fayl o'qildi:", data.length); // KEYIN (poll fazasi — 2.7)
});
console.log("B: tugadi");
// Tartib: A B C (fayl o'qilayotganda server boshqa ishni bajaradi)Misol 3 — Event loop tartibi (2.7, 2.8, 2.9) — intervyu klassikasi
console.log("1 — sinxron (birinchi)");
setTimeout(() => console.log("6 — setTimeout (timers)"), 0); // timers (2.7)
setImmediate(() => console.log("5 — setImmediate (check)")); // check (2.7)
Promise.resolve().then(() => console.log("4 — Promise (microtask)")); // (2.8)
process.nextTick(() => console.log("3 — nextTick (eng oldin)")); // (2.8)
console.log("2 — sinxron (ikkinchi)");
// NATIJA:
// 1 — sinxron (birinchi) sinxron kod birinchi
// 2 — sinxron (ikkinchi) barcha sinxron tugaydi
// 3 — nextTick nextTick navbati (2.8: eng yuqori)
// 4 — Promise microtask navbati
// 5 — setImmediate (yoki 6) macrotask fazalar
// 6 — setTimeout
// Saboq: sinxron nextTick Promise timer/check (2.8)Misol 4 — setTimeout vs setImmediate (2.9)
// I/O callback ICHIDA: setImmediate DOIM setTimeout'dan oldin (poll check)
const fs = require("fs");
fs.readFile(__filename, () => { // poll fazasi (2.7)
setTimeout(() => console.log("setTimeout"), 0); // timers (keyingi tsikl)
setImmediate(() => console.log("setImmediate")); // check (DARROV poll'dan keyin)
});
// I/O ichida DOIM: "setImmediate" "setTimeout"
// (poll tugagach check keladi; timers keyingi aylanishda — 2.7)Misol 5 — process.nextTick "starvation" xavfi (2.9)
// XAVFLI — nextTick ichida nextTick event loop QOTADI
let son = 0;
function cheksizTick() {
if (son < 5) { // (chegara qo'ydik — aks holda mangu)
console.log("nextTick", ++son);
process.nextTick(cheksizTick); // har fazadan oldin yana qo'shadi (2.8)
}
}
process.nextTick(cheksizTick);
setTimeout(() => console.log("Men ham bormi?"), 0);
// nextTick'lar TUGAGUNCHA setTimeout (timer) ishlamaydi (2.8)
// Agar chegara bo'lmasa — setTimeout HECH QACHON ishlamaydi (starvation!)Misol 6 — Thread pool (parallel crypto — 2.10, 2.11)
const crypto = require("crypto"); // (5.3)
// pbkdf2 — CPU-og'ir (thread pool'da, default 4 — 2.10)
const boshlanish = Date.now();
for (let i = 1; i <= 4; i++) {
crypto.pbkdf2("parol", "tuz", 100000, 64, "sha512", () => {
console.log(`${i}: ${Date.now() - boshlanish}ms`); // ~bir vaqtda (parallel!)
});
}
// 4 ta bir vaqtda tugaydi (4 thread — 2.10). 5-chi bo'lsa — kutardi.
// UV_THREADPOOL_SIZE=8 node app.js bilan 8 thread (2.10)Misol 7 — Event loop'ni bloklash (og'ir hisob) va yechim
// XATO — og'ir sinxron hisob event loop'ni bloklaydi (0.5: sahifa qotishi)
const http = require("http");
http.createServer((req, res) => {
// Har so'rovda OG'IR hisob — BUTUN server qotadi (boshqalar kutadi!)
let yigindi = 0;
for (let i = 0; i < 1e9; i++) yigindi += i; // CPU-og'ir, bloklaydi (2.5)
res.end(`Natija: ${yigindi}`);
}).listen(3000);
// YECHIM — og'ir CPU ishni Worker Thread'ga chiqarish (alohida thread)
// const { Worker } = require("worker_threads"); (5.4 ga bog'liq)
// Yoki ishni bo'laklab, setImmediate bilan navbatga qo'yish
// Saboq: Node tarmoq I/O uchun ajoyib, lekin CPU-og'ir ish uchun ehtiyot (2.11)Misol 8 — process obyekti (argv, env, events — 2.12)
// Environment variable 5.8-bob — DEFAULT bilan
const PORT = process.env.PORT || 3000;
console.log("Port:", PORT); // PORT=8080 node app.js 8080
// Process eventlari (5.4: EventEmitter)
process.on("exit", (kod) => {
console.log(`Process tugadi, kod: ${kod}`); // tozalash uchun (0.2)
});
process.on("uncaughtException", (xato) => { // ushlanmagan xato (2.12)
console.error("Halokatli xato:", xato.message);
process.exit(1); // 1 — xato bilan tugash (0.3: exit kod)
});
console.log("Dastur ishlayapti...");
// process.exit(0); // ataylab to'xtatish (0 — muvaffaqiyat)Misol 9 — Oddiy HTTP server (scalability namoyishi — 2.5)
const http = require("http"); // (5.5 da chuqur)
// Bitta thread, lekin minglab so'rovni uddalaydi (non-blocking — 2.5)
const server = http.createServer((req, res) => {
// Har so'rov — "event"; yangi thread OCHILMAYDI (2.5)
console.log(`So'rov: ${req.method} ${req.url}`); // (0.4: metod, url)
res.writeHead(200, { "Content-Type": "application/json" }); // (0.4: status)
res.end(JSON.stringify({ xabar: "Salom, backend!", vaqt: Date.now() }));
});
server.listen(3000, () => {
console.log("Server http://localhost:3000 da ishlayapti");
});
// node app.js brauzerda localhost:3000
// Bu server bitta thread bilan minglab ulanishni uddalaydi (event loop — 2.7)5. To'g'ri va noto'g'ri holatlar
1) Server'da blocking (Sync) API
// butun serverni to'xtatadi 2.6-bob — barcha foydalanuvchi kutadi
const data = fs.readFileSync("katta.txt");
// non-blocking (async — 2.11)
const data = await fs.promises.readFile("katta.txt");2) Event loop'ni og'ir CPU bilan bloklash
// og'ir tsikl/hisob handler ichida server qotadi (Misol 7)
for (let i = 0; i < 1e9; i++) {...}
// Worker Thread, bo'laklash, yoki tashqi xizmat (2.11)3) process.nextTick ni rekursiv ishlatish
// starvation — event loop qotadi (2.9, Misol 5)
function f() { process.nextTick(f); }
// rekursiv kechiktirish kerak bo'lsa — setImmediate (check fazasi)
function f() { setImmediate(f); }4) Xatoni async'da ushlamaslik
// callback'da err tekshirilmadi (2.12)
fs.readFile("yoq.txt", (err, data) => { console.log(data.length); });
// err bo'lsa, data undefined xato
// doim err tekshir (Node callback konvensiyasi: err birinchi)
fs.readFile("yoq.txt", (err, data) => {
if (err) return console.error(err.message);
console.log(data.length);
});5) Brauzer API'sini Node'da kutish
// Node'da DOM/window yo'q (2.14)
document.querySelector(...); // ReferenceError
localStorage.setItem(...); // yo'q
// Node API: fs, process, global (2.12, 2.14)6. Keng tarqalgan xatolar va yechimlari
Xato 1 — ReferenceError: document is not defined (yoki window/localStorage)
Sababi: brauzer API'si Node'da yo'q 2.14-bob. Yechimi: server kodda DOM ishlatmang; Node API (fs, http) ishlating.
Xato 2 — Server sekin/qotib qoladi
Sababi: blocking API yoki og'ir CPU event loop'ni bloklaydi (2.5, 2.6). Yechimi: async API; og'ir ishni Worker Thread'ga (2.11, Misol 7).
Xato 3 — Error: EADDRINUSE: address already in use :::3000
Sababi: 3000-port band (0.2, 0.4). Yechimi: boshqa port; yoki band process'ni topib to'xtat (0.3: lsof/netstat).
Xato 4 — Cannot find module 'x'
Sababi: modul o'rnatilmagan yoki yo'l xato (2.14, 0.7). Yechimi: npm install x; core modul nomini tekshiring (fs, http).
Xato 5 — Async natija undefined
Sababi: async amal tugashini kutmasdan natijaga murojaat 2.11-bob. Yechimi: callback/Promise/await ichida ishlating; event loop tartibini eslang 2.8-bob.
Xato 6 — UnhandledPromiseRejection (Node process qulashi)
Sababi: ushlanmagan Promise rad etilishi 2.11-bob. Yechimi: try/catch/.catch 2.12-bob; process.on("unhandledRejection").
7. Integratsiya — bu mavzu stack'ning qayerida uchraydi
- JavaScript (2-QISM): Node — JS'ni serverda ishlatadi; async 2.11-bob — event loop ustida.
- 0.1, 0.2, 0.5: thread 0.1-bob, process 0.2-bob, V8/event loop kirishi 0.5-bob — bu yerda chuqurlashadi.
- npm/modullar (5.2, 2.14): Node ekotizimi.
- Core modullar 5.3-bob: fs/http/crypto — libuv ustida.
- Streams/Events 5.4-bob: event loop bilan ishlaydi.
- HTTP/Express (5.5, 5.6): server — event loop'da ishlaydi.
- NestJS (8): Node ustiga qurilgan.
- Performance 15.5-bob: event loop bloklash — debug.
8. Eng yaxshi amaliyotlar (best practices)
- Server'da hech qachon blocking (
...Sync) API — doim async 2.6-bob. - Event loop'ni bloklamang — og'ir CPU ishni Worker Thread'ga; tarmoq I/O Node'ning kuchi 2.11-bob.
- Async callback'larda
errni doim tekshiring (Node konvensiyasi — error-first — 4-holat). process.nextTickni ehtiyot bilan — starvation xavfi; ko'pinchasetImmediateyoki Promise afzal 2.9-bob.- Promise/async-await ishlating (callback hell o'rniga — 2.11).
- Event loop tartibini tushuning — nextTick Promise timer/immediate 2.8-bob; performance/debug uchun.
UV_THREADPOOL_SIZE— ko'p fayl/crypto ishlatadigan ilovada oshiring 2.10-bob.process.envbilan konfiguratsiya 5.8-bob;__dirnamebilan yo'l 0.2-bob.- Ushlanmagan xato/rejection'ni boshqar (
process.on— 6-holat).
9. Amaliy loyiha: "Event Loop Laboratoriyasi va Birinchi Server"
Node'ning yuragini — event loop va non-blocking I/O'ni — amalda his qilish.
Maqsad
Event loop fazalarini, microtask ustuvorligini, blocking vs non-blocking farqini va thread pool'ni amalda tajriba qilib, mustahkam tushuncha hosil qilish.
Talablar (requirements)
- Event loop tartibi:
console.log,setTimeout,setImmediate,Promise.then,process.nextTickni aralashtirib, natija tartibini avval bashorat qiling, keyin ishlatib tekshiring (Misol 3, 2.8). - Blocking vs non-blocking: bir faylni
readFileSyncvareadFilebilan o'qib, ularning oqim tartibini va "qotish" farqini ko'rsating (Misol 2, 2.6). - setTimeout vs setImmediate: I/O callback ichida va tashqarisida farqini ko'rsating (Misol 4, 2.9).
- Thread pool: 4 va 8 ta
crypto.pbkdf2ni parallel ishlatib, vaqtlarni o'lchang;UV_THREADPOOL_SIZEo'zgartirib farqni ko'ring (Misol 6, 2.10). - Event loop bloklash: og'ir CPU tsikl bilan serverni bloklab, keyin yechim (bo'laklash yoki Worker) bilan tuzating (Misol 7, 2.11).
processtahlili:argv,env,platform,cwdni chiqaruvchi CLI; argument va env bilan ishlash (Misol 8, 2.12).- Birinchi HTTP server: so'rovlarni loglovchi, JSON qaytaruvchi server (Misol 9); brauzer/curl bilan sinang 0.4-bob.
- Har tajriba uchun nima sodir bo'lishini va NEGA ekanini izohda yozing (event loop fazasi bilan).
Maslahatlar (hint)
- Tartibni avval qog'ozga bashorat qiling 2.8-bob, keyin ishlatib solishtiring — bu eng yaxshi o'rganish.
console.time/timeEnd0.5-bob bilan thread pool/blocking vaqtini o'lchang.UV_THREADPOOL_SIZE=8 node app.js(Git Bash'da — 0.3).- HTTP server:
http.createServer+res.end(Misol 9, 5.5 da chuqur). - Blocking demoda — server ishlayotganda boshqa so'rov yuborib, "qotish"ni his qiling.
process.argv[2]— birinchi haqiqiy argument 0.3-bob.
"Tayyor" mezonlari (acceptance criteria)
- Event loop tartibi bashorat qilingan va tekshirilgan (nextTick Promise timer/immediate).
- Blocking vs non-blocking farqi ko'rsatilgan va izohlangan.
- setTimeout vs setImmediate (I/O ichida/tashqarisida) farqi ko'rsatilgan.
- Thread pool 4 vs 8 vaqti o'lchangan.
- Event loop bloklash muammosi va yechimi ko'rsatilgan.
-
processCLI argument/env bilan ishlaydi. - HTTP server so'rovlarni loglaydi va JSON qaytaradi.
- Har tajriba "nima va nega" izohi bilan.
Yechim kodi ataylab berilmagan — bu loyihani o'zingiz yozib ko'ring.
10. Xulosa va keyingi bobga ko'prik
Bu bobda Node.js'ning yuragini chuqur ochdik:
- Node.js — runtime (til/framework emas): V8 (JS bajaradi — 0.5) + libuv (event loop, I/O — C) + Node API (fs/http).
- Single-threaded JS + non-blocking I/O — bitta thread bilan minglab ulanish (tarmoq native async, fayl/CPU — thread pool).
- Event loop (libuv) 6 faza: timers pending idle/prepare poll (I/O) check (setImmediate) close.
- Microtask navbatlari (Node runtime, fazalar orasida): nextTick (eng yuqori) Promise.
- Ustuvorlik: sinxron nextTick Promise timer/I/O/check.
- Thread pool (default 4) — fayl/DNS/crypto; tarmoq esa OS native (pool'siz).
process— argv/env/exit; server'da hech qachon blocking API.
Keyingi bob — 5.2-bob: npm, package.json, dependencies, scripts, semver. Node'ning ishlashini bildik; endi uning ekotizimini — millionlab paketni boshqaradigan npmni chuqur o'rganamiz (0.7-bobda boshlagandik). package.json, dependency turlari, scripts, semantic versioning — har bir Node/frontend loyihaning poydevori.
Foydalanilgan rasmiy/ishonchli manbalar
- nodejs.org/learn — The Node.js Event Loop, Timers, and process.nextTick
- docs.libuv.org — libuv design overview, event loop, thread pool
- Node.js rasmiy hujjatlari — V8, libuv, process, global obyektlar
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!