5.4-bob: Events (EventEmitter) va Streams (chuqur)
5-QISM — Node.js Backend · 4-mavzu
1. Kirish va motivatsiya
Core modullarni 5.3-bob bildik. Endi Node'ning ikki fundamental, event-asoslangan tushunchasini chuqur o'rganamiz — bularsiz Node'ning ichki ishlashini to'liq tushunib bo'lmaydi:
EventEmitter — "hodisa chiqarish va tinglash" mexanizmi. Bu shunchaki bir modul emas — Node'ning butun arxitekturasi event-driven (hodisaga asoslangan). HTTP server (
req,res), streams,process5.1-bob — hammasi EventEmitter. 2.16-bobdagi brauzer eventlari (DOM) ning server tomondagi ukasi.Streams — katta ma'lumotni xotirani to'ldirmasdan, bo'lak-bo'lak (chunk) qayta ishlash (0.1: RAM cheklangan). 5.1-bobda "5 GB faylni
readFileSyncbilan o'qima — RAM portlaydi" degandik. Streams aynan shu muammoni hal qiladi: ma'lumot oqim kabi oqib o'tadi, hech qachon to'liq xotirada bo'lmaydi.
O'xshatish (EventEmitter): radio stansiya. Stansiya (emitter) signal chiqaradi (
emit); tinglovchilar (listeners) o'sha to'lqinga ulanib (on), eshitadi. Stansiya kim eshitayotganini bilmaydi — shunchaki chiqaradi. Bu — decoupling (qismlarni ajratish): chiqaruvchi va tinglovchi bir-biriga bog'liq emas.O'xshatish (Streams): hovuzni chelaklab ko'chirish vs shlang orqali.
readFileSync— butun hovuzni bitta ulkan idishga quyib, keyin ko'chirish (idish yetmasligi mumkin — RAM). Stream — shlang: suv oqib o'tadi, hech qachon hammasi bir joyda turmaydi. 100 GB faylni 50 MB RAM bilan ham qayta ishlaysiz.
Nega muhim?
- Node arxitekturasi event-driven — EventEmitter'ni bilmasdan, server (
req/res), socket 5.13-bob tushunarsiz. - Katta ma'lumot (fayl, video, DB natija, HTTP body) — streams'siz xotira muammosi 0.1-bob.
- Performance — streams xotira-samarali, tez (ma'lumot kelishi bilan qayta ishlanadi).
- HTTP 5.5-bob, file upload 5.11-bob, socket.io 5.13-bob — streams/events ustida.
2. Nazariya — chuqur tushuntirish (EventEmitter)
2.1. Event-driven arxitektura nima?
Event-driven (hodisaga asoslangan) — dastur "hodisalar"ga javob berib ishlaydi (so'rov keldi, fayl o'qildi, ulanish yopildi), ketma-ket buyruq bajarish o'rniga. Node'ning butun modeli shunday (5.1: event loop ham shu — eventlarni boshqaradi).
ANANAVIY (imperativ): qadam1 qadam2 qadam3 (ketma-ket)
EVENT-DRIVEN: "so'rov" eventi handler; "xato" eventi handler
(qachon nima sodir bo'lishi oldindan noma'lum)2.2. EventEmitter — asosiy mexanizm
EventEmitter — node:events core modulidagi class 5.3-bob. U "hodisa chiqarish" (emit) va "tinglash" (on) imkonini beradi (nodejs.org):
import { EventEmitter } from "node:events";
const emitter = new EventEmitter();
// Tinglash (listener qo'shish) — 2.16: addEventListener kabi
emitter.on("salom", (ism) => {
console.log(`Salom, ${ism}!`);
});
// Chiqarish (event yuborish) — barcha "salom" listenerlari ishlaydi
emitter.emit("salom", "Ali"); // "Salom, Ali!"
emitter.emit("salom", "Vali"); // "Salom, Vali!"2.3. EventEmitter metodlari
emitter.on("event", listener); // tinglash (har emit'da)
emitter.once("event", listener); // FAQAT BIR MARTA (keyin avtomatik o'chadi)
emitter.emit("event", arg1, arg2); // chiqarish (sinxron! — 2.5)
emitter.off("event", listener); // listener o'chirish (removeListener)
emitter.removeAllListeners("event"); // hammasi
emitter.listenerCount("event"); // nechta listener
emitter.eventNames(); // barcha event nomlari
emitter.prependListener("event", fn); // birinchi qilib qo'shish
onvsonce:on— haremitda ishlaydi (doimiy).once— faqat birinchi marta (masalan "ulanish ochildi", "server tayyor" — bir martalik hodisalar).
2.4. Eventlar — SINXRON (muhim nuans)
emit — sinxron: listenerlar darrov, navbat bilan (ro'yxatga qo'shilgan tartibda) ishlaydi, emit qatori tugaguncha (2.5: 5.1 event loop bilan adashtirma):
emitter.on("ish", () => console.log("2: listener"));
console.log("1: emitdan oldin");
emitter.emit("ish"); // listener DARROV ishlaydi (sinxron)
console.log("3: emitdan keyin");
// Tartib: 1 2 3 (emit listener'ni darrov, sinxron chaqiradi)Agar listenerda async ish kerak bo'lsa — listener ichida async/Promise ishlating (lekin emit ularni kutmaydi).
2.5. error eventi — maxsus va xavfli
error eventi — EventEmitter'da maxsus: agar error chiqarilsa va listener yo'q bo'lsa, Node butun process'ni qulatadi (uncaught exception — 5.1, 2.12):
const emitter = new EventEmitter();
// error listener yo'q emit("error") process'ni qulatadi
// emitter.emit("error", new Error("xato")); // CRASH!
// doim error listener qo'shing
emitter.on("error", (err) => {
console.error("Xato ushlandi:", err.message); // (2.12)
});
emitter.emit("error", new Error("biror xato")); // endi xavfsizHar EventEmitter'da
errorlistener bo'lsin (stream, socket — 5.13). Aks holda bitta xato butun serverni o'ldiradi 5.1-bob.
2.6. Memory leak ogohlantirishi
Har EventEmitter'da default 10 ta listener chegarasi (ogohlantirish uchun). Agar ko'proq qo'shsangiz:
MaxListenersExceededWarning: Possible EventEmitter memory leak detected.
11 "data" listeners added.Sababi: odatda listener'larni off qilmasdan qayta-qayta on qilish (memory leak — 0.1). Yechimi: kerakmas listener'larni off qiling; haqiqatan ko'p kerak bo'lsa emitter.setMaxListeners(n).
2.7. Custom EventEmitter (o'z class — 2.10)
O'z class'ingni EventEmitter'dan meros qilib (2.10: inheritance), event chiqaruvchi qilasiz:
import { EventEmitter } from "node:events";
class Buyurtma extends EventEmitter { // (2.10: extends)
yarat(mahsulot) {
// ... biznes logika ...
this.emit("yaratildi", mahsulot); // event chiqar
}
tolov() {
this.emit("tolandi");
}
}
const buyurtma = new Buyurtma();
buyurtma.on("yaratildi", (m) => console.log(`Buyurtma: ${m}`)); // email yubor (5.19)
buyurtma.on("tolandi", () => console.log("To'lov qabul qilindi")); // SMS (5.18)
buyurtma.yarat("Telefon"); // "Buyurtma: Telefon"Nega kuchli (decoupling):
yaratmetodi email/SMS yuborishni bilmaydi — u faqat event chiqaradi. Email/SMS logikasi alohida listener'da. Yangi reaksiya qo'shsangiz (masalan log),yaratni o'zgartirmaysiz (9.1: Open/Closed). Bu — observer pattern 9.2-bob.
3. Nazariya — chuqur tushuntirish (Streams)
3.1. Stream nima va nega kerak (0.1)
Stream (oqim) — ma'lumotni bo'lak-bo'lak (chunk), vaqt o'tishi bilan qayta ishlash (hammasini birdan emas):
readFileSync (butun fayl xotiraga):
[████████████ 5 GB ████████████] RAM'da 5 GB! (portlaydi — 0.1)
Stream (chunk-chunk):
[64KB] qayta ishla tashla [64KB] qayta ishla ...
RAM'da bir vaqtda faqat 64KB (5 GB faylni 64KB bilan!)Foydalari: xotira-samarali (katta fayl/cheksiz ma'lumot), tez (birinchi chunk kelishi bilan boshlaydi, hammasini kutmaydi), kompozitsion (pipe bilan ulanadi).
3.2. Stream — EventEmitter (bog'lanish)
Barcha streamlar — EventEmitter (3-bo'lim, nodejs.org). Ular holatni eventlar bilan bildiradi:
Readable: "data" (chunk keldi), "end" (tugadi), "error"
Writable: "drain" (yana yozsa bo'ladi), "finish" (tugadi), "error"Shuning uchun 2-bo'lim (EventEmitter) — streamlar uchun poydevor.
3.3. To'rt stream turi
Node'da to'rt fundamental stream turi (nodejs.org):
| Tur | Ma'nosi | Misol |
|---|---|---|
| Readable | o'qiladigan (manba) | fs.createReadStream, HTTP req |
| Writable | yoziladigan (manzil) | fs.createWriteStream, HTTP res |
| Duplex | o'qiladigan va yoziladigan | TCP socket (5.13) |
| Transform | Duplex + ma'lumotni o'zgartiradi | zlib (siqish), shifrlash |
3.4. Readable stream — o'qish
import { createReadStream } from "node:fs";
const stream = createReadStream("katta.txt", { encoding: "utf8", highWaterMark: 64 * 1024 });
// highWaterMark — chunk hajmi (default 64KB)
stream.on("data", (chunk) => { // har chunk kelganda (2.2: on)
console.log(`Chunk: ${chunk.length} belgi`);
});
stream.on("end", () => { // hammasi o'qildi
console.log("Fayl to'liq o'qildi");
});
stream.on("error", (err) => { // xato (2.5: MAJBURIY)
console.error("Xato:", err.message);
});3.5. Writable stream — yozish
import { createWriteStream } from "node:fs";
const stream = createWriteStream("natija.txt");
stream.write("Birinchi qator\n"); // yozish (chunk)
stream.write("Ikkinchi qator\n");
stream.end("Oxirgi qator\n"); // tugatish (oxirgi yozuv + yopish)
stream.on("finish", () => console.log("Yozish tugadi")); // (3.2)
stream.on("error", (err) => console.error(err));3.6. Backpressure — eng muhim tushuncha
Backpressure (orqa bosim) — Readable tez ma'lumot bersa, lekin Writable sekin yozsa, ma'lumot to'planib qoladi (xotira to'ladi — 0.1). Node buni boshqaradi (nodejs.org):
Readable (tez) ── Writable (sekin)
buffer to'ldi! (highWaterMark oshdi)
write() false qaytaradi Readable'ni TO'XTAT (pause)
Writable bo'shadi "drain" eventi Readable'ni DAVOM ETTIR (resume)// write() false qaytarsa — to'xtatish kerak (qo'lda murakkab)
const ok = writable.write(chunk);
if (!ok) {
readable.pause(); // to'xtat (buffer to'la)
writable.once("drain", () => readable.resume()); // bo'shaganda davom
}
// Lekin buni QO'LDA qilmang — pipe/pipeline avtomatik qiladi (3.7)Backpressure'ni qo'lda boshqarish murakkab va xatoga moyil. Shuning uchun
pipe/pipelineishlatamiz — ular backpressure'ni avtomatik boshqaradi 3.7-bob. Bu — streams'ning eng katta amaliy qoidasi.
3.7. pipe va pipeline — ulash (eng amaliy)
pipe — Readable'ni Writable'ga ulaydi; backpressure avtomatik 3.6-bob:
import { createReadStream, createWriteStream } from "node:fs";
// Faylni nusxalash (xotira-samarali — har qanday hajm)
createReadStream("manba.txt").pipe(createWriteStream("nusxa.txt"));
// Readable Writable, backpressure avtomatik (3.6)Lekin pipe xatolarni to'g'ri boshqarmaydi va resurslarni tozalamaydi. Production uchun pipeline (xato + tozalash + callback/Promise — nodejs.org):
import { pipeline } from "node:stream/promises";
// Production — pipeline (xato boshqaruvi + tozalash — 2.12)
await pipeline(
createReadStream("manba.txt"),
createWriteStream("nusxa.txt")
);
// Xato bo'lsa — throw qiladi (try/catch bilan ushlanadi), resurslar yopiladiProduction'da
pipeemas,pipelineishlating (nodejs.org).pipeda xato bo'lsa — stream "osilib" qoladi, memory leak.pipeline— xatoni uzatadi va tozalaydi.
3.8. Transform stream — ma'lumotni o'zgartirish
Transform — o'qib, o'zgartirib, yozadi (gzip, shifrlash, formatlash):
import { createReadStream, createWriteStream } from "node:fs";
import { createGzip } from "node:zlib";
import { pipeline } from "node:stream/promises";
// Faylni siqish (gzip — Transform stream)
await pipeline(
createReadStream("katta.log"),
createGzip(), // Transform: siqadi (3.3)
createWriteStream("katta.log.gz")
);
// O'qiladi siqiladi yoziladi, hammasi oqim bilan (xotira-samarali)3.9. O'z Transform stream'ing
import { Transform } from "node:stream";
// Har chunkni katta harfga aylantiruvchi Transform
const kattaHarf = new Transform({
transform(chunk, encoding, callback) {
this.push(chunk.toString().toUpperCase()); // o'zgartirib uzat (2.6)
callback(); // tugadi (xato bo'lsa callback(err))
}
});
// Ishlatish: readStream.pipe(kattaHarf).pipe(writeStream)3.10. Stream rejimlari va Buffer (0.1)
- Buffer — binary ma'lumot (0.1: bayt); stream chunk'lari default Buffer (encoding berilmasa).
- flowing vs paused — Readable'ning ikki rejimi:
pipe/on("data")— flowing (avtomatik oqadi);read()— paused (qo'lda). - Object mode — chunk Buffer emas, obyekt bo'lishi mumkin (
objectMode: true) — DB natijalari uchun.
4. Sintaksis — tez ma'lumotnoma
// EventEmitter
import { EventEmitter } from "node:events";
e.on(ev, fn) e.once(ev, fn) e.emit(ev, ...args) e.off(ev, fn)
e.on("error", fn) // MAJBURIY (2.5)
class X extends EventEmitter {} // custom (2.7)
// Streams
import { createReadStream, createWriteStream } from "node:fs";
import { pipeline } from "node:stream/promises";
rs.on("data"/"end"/"error", fn) ws.write(x) ws.end()
await pipeline(rs, transform, ws) // production 3.7-bob — pipe emas!5. Batafsil kod namunalari
Misol 1 — Custom EventEmitter (buyurtma tizimi — 2.7)
import { EventEmitter } from "node:events";
class BuyurtmaTizimi extends EventEmitter {
yarat(buyurtma) {
console.log(`Buyurtma #${buyurtma.id} yaratildi`);
this.emit("yaratildi", buyurtma); // event (2.2)
}
tolandi(buyurtma) {
this.emit("tolandi", buyurtma);
}
}
const tizim = new BuyurtmaTizimi();
// Turli reaksiyalar — decoupled (2.7)
tizim.on("yaratildi", (b) => console.log(` Email: buyurtma #${b.id} 5.19-bob`));
tizim.on("yaratildi", (b) => console.log(` Statistika yangilandi`));
tizim.once("tolandi", (b) => console.log(` Birinchi to'lov!`)); // (2.3: once)
tizim.on("error", (err) => console.error("Xato:", err.message)); // (2.5)
tizim.yarat({ id: 1, mahsulot: "Telefon" });
tizim.tolandi({ id: 1 });
// yarat ikkala "yaratildi" listener ishlaydi (sinxron — 2.4)Misol 2 — Readable stream bilan katta fayl (3.4)
import { createReadStream } from "node:fs";
// 10 GB faylni ham xotirani to'ldirmasdan o'qish (0.1, 3.1)
let qatorlar = 0;
const stream = createReadStream("katta.log", { encoding: "utf8" });
stream.on("data", (chunk) => { // har 64KB (3.4)
qatorlar += chunk.split("\n").length - 1; // qatorlarni sanang (2.6)
});
stream.on("end", () => console.log(`Jami qator: ${qatorlar}`));
stream.on("error", (err) => console.error(err)); // (2.5)
// readFileSync 10 GB'ni RAM'ga sig'dirolmaydi; stream — bemalolMisol 3 — pipeline bilan fayl nusxalash va siqish (3.7, 3.8)
import { createReadStream, createWriteStream } from "node:fs";
import { createGzip } from "node:zlib";
import { pipeline } from "node:stream/promises";
// Xavfsiz nusxalash (backpressure + xato avtomatik — 3.6, 3.7)
async function nusxala(manba, manzil) {
try {
await pipeline(createReadStream(manba), createWriteStream(manzil));
console.log("Nusxalandi");
} catch (err) {
console.error("Nusxalash xatosi:", err.message); // (2.12)
}
}
// Log faylni siqish (Transform — 3.8)
async function siq(fayl) {
await pipeline(
createReadStream(fayl),
createGzip(), // siqadi (3.8)
createWriteStream(`${fayl}.gz`)
);
}Misol 4 — O'z Transform stream (CSV JSON — 3.9)
import { Transform } from "node:stream";
// Har qatorni (CSV) JSON'ga aylantiruvchi Transform
const csvToJson = new Transform({
readableObjectMode: true, // chiqish — obyekt (3.10)
transform(chunk, enc, cb) {
const qatorlar = chunk.toString().trim().split("\n");
for (const qator of qatorlar) {
const [ism, yosh] = qator.split(","); // (2.6: split)
this.push({ ism, yosh: Number(yosh) }); // obyekt uzat (2.8)
}
cb(); // tugadi (3.9)
}
});
// createReadStream("users.csv").pipe(csvToJson).on("data", u => console.log(u))Misol 5 — HTTP server'da stream (5.5 ga ko'prik — 3.2)
import http from "node:http";
import { createReadStream } from "node:fs";
// Katta faylni stream bilan yuborish (xotira-samarali — 3.1)
http.createServer((req, res) => { // req — Readable, res — Writable! (3.3)
if (req.url === "/video") {
// readFile bilan: butun video RAM'ga, keyin yuborish
// stream bilan: oqim, RAM-samarali
createReadStream("katta-video.mp4").pipe(res); // (3.7)
}
}).listen(3000);
// req va res — streamlar (EventEmitter — 3.2); pipe avtomatik backpressureMisol 6 — error event xavfi (2.5)
import { createReadStream } from "node:fs";
const stream = createReadStream("yoq-fayl.txt");
// error listener bo'lmasa process QULAYDI (2.5)
// doim error tinglang
stream.on("error", (err) => {
if (err.code === "ENOENT") console.log("Fayl topilmadi"); // (5.3: ENOENT)
else console.error(err);
});
stream.on("data", (c) => console.log(c.length));Misol 7 — once va listener boshqaruvi (2.3, 2.6)
import { EventEmitter } from "node:events";
const server = new EventEmitter();
// once — faqat birinchi marta (2.3)
server.once("ready", () => console.log("Server tayyor (bir marta)"));
// Listener'ni keyin o'chirish (memory leak'dan saqlanish — 2.6)
function logHandler(data) { console.log("Log:", data); }
server.on("log", logHandler);
// ... keyin kerak bo'lmasa:
server.off("log", logHandler); // o'chir (2.6)
server.emit("ready"); // ishlaydi
server.emit("ready"); // ENDI ishlamaydi (once — 2.3)6. To'g'ri va noto'g'ri holatlar
1) Katta faylni readFile bilan
// butun fayl RAM'ga — katta faylda xotira portlaydi (0.1, 3.1)
const data = await readFile("5gb.mp4");
// stream
createReadStream("5gb.mp4").pipe(res); // (3.7)2) Production'da pipe (pipeline o'rniga)
// pipe — xato boshqarilmaydi, resurs oqishi (3.7)
rs.pipe(ws);
// pipeline — xato + tozalash
await pipeline(rs, ws);3) error listener'siz stream/emitter
// error process qulaydi (2.5)
stream.on("data", ...); // error yo'q
// doim error
stream.on("error", err => ...);4) Listener'larni off qilmaslik (memory leak)
// qayta-qayta on, off yo'q MaxListenersExceededWarning (2.6)
setInterval(() => emitter.on("tick", fn), 1000);
// once yoki off
emitter.once("tick", fn);7. Keng tarqalgan xatolar va yechimlari
Xato 1 — MaxListenersExceededWarning
Sababi: 10+ listener (off qilinmagan — memory leak — 2.6). Yechimi: kerakmas listenerlarni off; haqiqatan ko'p bo'lsa setMaxListeners.
Xato 2 — Process qulaydi (uncaught error)
Sababi: stream/emitter error eventi listener'siz 2.5-bob. Yechimi: har emitter/stream'da on("error", ...).
Xato 3 — Xotira to'lib ketadi (katta fayl)
Sababi: readFile/butun ma'lumotni xotiraga 3.1-bob. Yechimi: stream + pipeline 3.7-bob.
Xato 4 — Stream "osilib" qoladi (tugamaydi)
Sababi: pipeda xato yoki backpressure noto'g'ri (3.6, 3.7). Yechimi: pipeline (avtomatik tozalash).
Xato 5 — emit natijasini async kutish
Sababi: emit sinxron — async listenerni kutmaydi 2.4-bob. Yechimi: async natija kerak bo'lsa Promise/callback alohida; events.once(emitter, "event") (Promise).
8. Integratsiya — bu mavzu stack'ning qayerida uchraydi
- Node arxitekturasi 5.1-bob: event-driven; event loop eventlarni boshqaradi.
- Core modullar 5.3-bob:
fsstream'lari;cryptostream'lari. - HTTP 5.5-bob:
req(Readable),res(Writable) — streamlar va EventEmitter (Misol 5). - File upload 5.11-bob: Multer — stream ustida.
- Socket.io 5.13-bob: event-driven (real-time).
- DOM events 2.16-bob: brauzer tomondagi o'xshashi.
- Observer pattern 9.2-bob: EventEmitter — observer'ning amali.
- Buffer 0.1-bob: stream chunk'lari.
9. Eng yaxshi amaliyotlar (best practices)
- Katta/cheksiz ma'lumot — stream (readFile emas — 3.1, xotira).
- Production'da
pipeline(pipeemas — xato + tozalash — 3.7). - Har emitter/stream'da
errorlistener (process qulashidan saqlaydi — 2.5). - Listener'larni
off/oncebilan boshqaring (memory leak — 2.6). emitsinxron ekanini eslang 2.4-bob; async kerak bo'lsa alohida.- Custom EventEmitter bilan decoupling (observer — 2.7, 9.2).
- Transform bilan oqim ichida o'zgartiring (gzip, format — 3.8).
- Backpressure'ni qo'lda boshqarmang — pipe/pipeline qiladi 3.6-bob.
10. Amaliy loyiha: "Log Qayta Ishlash Quvuri (Stream Pipeline)"
EventEmitter va Streams'ni amalda mustahkamlash.
Maqsad
EventEmitter (decoupling, error), va Streams (Readable/Writable/Transform, pipeline, backpressure)ni birlashtirib, katta ma'lumotni xotira-samarali qayta ishlash.
Talablar (requirements)
- Custom EventEmitter:
BuyurtmaTizimi—yarat/tolandi/bekoreventlari; bir nechta decoupled listener (email/SMS/log/statistika);errorlistener (Misol 1, 2.7). once: "birinchi buyurtma" kabi bir martalik hodisa (Misol 7, 2.3).- Katta fayl o'qish: katta log faylni stream bilan o'qib, qator/xato/maxsus so'z sanash (Misol 2, 3.4); xotira o'lchovini ko'ring (
process.memoryUsage()). - Transform: o'z Transform stream — har qatorni parse qilib (masalan log darajasi: INFO/ERROR), filtrlash yoki formatlash (Misol 4, 3.9).
- pipeline: o'qish transform (filtr) yozish (faqat ERROR qatorlarni alohida faylga — 3.7, 3.8).
- Gzip: natija faylni siqish (Transform — Misol 3, 3.8).
- Backpressure namoyishi: tez Readable + sekin Writable; pipeline avtomatik boshqarishini ko'rsating 3.6-bob.
- Xato boshqaruvi: mavjud bo'lmagan fayl, transform xatosi —
error/try-catch(2.5, 2.12). - Hammasi xotira-samarali (readFile emas — 3.1); xotira o'lchovini taqqoslab ko'rsating.
Maslahatlar (hint)
- EventEmitter:
class X extends EventEmitter2.7-bob; har emit'da bir nechtaon. - Stream:
createReadStream/createWriteStream(3.4, 3.5);pipelinefromstream/promises3.7-bob. - Transform:
new Transform({ transform(chunk, enc, cb) {...} })3.9-bob;cb()chaqiring. - Xotira:
process.memoryUsage().heapUsed5.1-bob — stream vs readFile farqi. errorlistener — har stream/emitter 2.5-bob.- Katta test fayl:
fs.appendFilebilan ko'p qator yarating.
"Tayyor" mezonlari (acceptance criteria)
- Custom EventEmitter bir nechta decoupled listener bilan ishlaydi.
-
oncebir martalik hodisada ishlaydi. - Katta fayl stream bilan o'qiladi (xotira past).
- O'z Transform stream parse/filtr qiladi.
- pipeline bilan o'qishtransformyozish ishlaydi.
- Natija gzip bilan siqiladi.
- Har stream/emitter'da error boshqarilgan.
- Xotira-samaradorlik (readFile bilan farq) ko'rsatilgan.
Yechim kodi ataylab berilmagan — bu loyihani o'zingiz yozib ko'ring.
11. Xulosa va keyingi bobga ko'prik
Bu bobda Node'ning ikki event-asoslangan ustunini chuqur o'rgandik:
- EventEmitter — hodisa chiqarish (
emit) / tinglash (on/once/off); Node arxitekturasining asosi (event-driven).emitsinxron;errorevent listener'siz process qulaydi; memory leak (10 listener); custom emitter — decoupling (observer — 9.2). - Streams — ma'lumotni bo'lak-bo'lak (chunk) qayta ishlash; xotira-samarali (katta fayl — 0.1). Hammasi EventEmitter. To'rt tur: Readable, Writable, Duplex, Transform.
- Backpressure — tez manba/sekin manzil muvozanati; qo'lda boshqarma — pipe/pipeline qiladi.
- Production'da
pipeline(pipeemas — xato + tozalash).
Keyingi bob — 5.5-bob: HTTP modul — server yaratish, request/response (qo'lda). Node'ning ichki mexanizmlarini (event, stream) bildik; endi 0.4-bobdagi HTTP nazariyasini amalga oshiramiz: faqat core http modul bilan (Express'siz!) server yaratamiz, so'rov va javobni qo'lda boshqaramiz. Bu — Express 5.6-bob "sehrini" tushunish uchun zarur poydevor.
Foydalanilgan rasmiy/ishonchli manbalar
- nodejs.org/api/events — EventEmitter (on/emit/once, error event, maxListeners)
- nodejs.org/api/stream — Readable/Writable/Duplex/Transform, pipe, pipeline
- nodejs.org/learn — Backpressuring in Streams, How to use Streams
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!