Server-Sent Events — bir tomonlama real-time
Muammodan boshlaylik
Foydalanuvchi katta faylni yukladi. Server qayta ishlamoqda. Foydalanuvchi progressni ko'rmoqchi:
Qayta ishlanmoqda... 20%
Qayta ishlanmoqda... 55%
Qayta ishlanmoqda... 90%
Tayyor! ✅
WebSocket ishlatishingiz mumkin — lekin u ikki tomonlama. Bu yerda faqat server → client yo'nalish kerak, client hech narsa yubormaydi. WebSocket bu holda ortiqcha murakkab.
SSE aynan shu uchun.
SSE nima?
SSE (Server-Sent Events) — serverdan clientga bir tomonlama uzluksiz ma'lumot oqimi.
WebSocket: client ◄──────────► server (ikki tomonlama)
SSE: client ◄─────────── server (faqat server → client)
Hayotiy o'xshatma
Radio stantsiya. Stantsiya uzatadi — siz eshitasiz. Siz stantsiyaga gapirolmaysiz. Aynan bir tomonlama kerak bo'lganda — SSE WebSocket dan sodda va qulay.
Qachon ishlatiladi:
- Fayl yuklash progressi
- Yangiliklar lenti
- Narx yangilanishlari
- Bildirish xabarlari
NestJS da SSE
@Sse() dekoratori Observable qaytaradi. Observable — vaqt o'tishi bilan bir necha qiymat beradigan ob'ekt. Har yangi qiymat clientga yuboriladi.
Fayl tuzilmasi
src/
progress/
progress.controller.ts
progress.module.ts
Kod
// progress/progress.controller.ts
import { Controller, Sse } from '@nestjs/common';
import { Observable } from 'rxjs';
@Controller('progress')
export class ProgressController {
@Sse('stream')
stream(): Observable<{ data: any }> {
let percent = 0;
return new Observable((subscriber) => {
const timer = setInterval(() => {
percent += 20;
subscriber.next({ data: { percent } }); // ← clientga yuborish
if (percent >= 100) {
subscriber.complete(); // ← oqim tugadi
clearInterval(timer);
}
}, 1000);
// Client uzilsa — timerni tozalash
return () => clearInterval(timer);
});
}
}
GET /progress/stream ga ulanganingizda — har soniyada { percent: 20 }, { percent: 40 } ... keladi.
Nima uchun { data: ... } format?
SSE protokoli shunday ishlaydi — har xabar data: prefiksi bilan yuboriladi. NestJS avtomatik qiladi, lekin ob'ektni { data: ... } ga o'rash shart.
// To'g'ri:
subscriber.next({ data: { percent: 20 } })
// Noto'g'ri:
subscriber.next({ percent: 20 }) // ← SSE standarti buziladi
Frontend dan qabul qilish
const eventSource = new EventSource('/progress/stream');
eventSource.onmessage = (event) => {
const data = JSON.parse(event.data);
console.log(`Progress: ${data.percent}%`);
if (data.percent >= 100) {
eventSource.close(); // ← tugadi, ulanishni yopamiz
}
};
EventSource — brauzerni o'zida bor, hech qanday kutubxona kerak emas.
SSE vs WebSocket
| SSE | WebSocket | |
|---|---|---|
| Yo'nalish | Server → client | Ikki tomonlama |
| Murakkablik | Sodda | Murakkabrok |
| Reconnect | Avtomatik | Qo'lda |
| Qachon | Progress, feed | Chat, o'yin |
Tez-tez uchraydigan xatolar
1. EventSource ishlamayapti
EventSource's response has a MIME type ("application/json") that is not "text/event-stream"
Sababi: @Sse() o'rniga @Get() ishlatilgan.
Yechim: @Sse('stream') dekoratorini tekshiring.
2. Client uzilganda timer to'xtamayapti
Sababi: Observable dan return () => clearInterval(timer) unutilgan.
Yechim: Cleanup funksiyasini qaytaring — server resursi sarf qilmaydi.
Xulosa
- SSE — serverdan clientga bir tomonlama oqim
@Sse()dekoratori — NestJS da ishlatishObservable— vaqt o'tishi bilan qiymat yubora oladi{ data: ... }formatida yuborish shart- Frontend da
EventSource— kutubxona shart emas - Progress, live feed, bildirishnomalar uchun ideal
Keyingi dars: 39-dars: Microservices — asoslar, RabbitMQ