WebSocket — real-time ulanish
Muammodan boshlaylik
Chat ilovasi yozyapsiz. Ali Vali ga xabar yozdi. Vali o'z sahifasida o'tiribdi — yangi xabar kelganini qanday biladi?
Birinchi fikr: har 2 soniyada serverga so'rov yuborish — "yangi xabar bormi?"
setInterval(async function() {
const javob = await fetch("/api/xabarlar/yangi");
const xabarlar = await javob.json();
if (xabarlar.length > 0) ko_rsat(xabarlar);
}, 2000);
Bu — polling. Ishlaydi. Lekin muammo bor.
Bir soatda 1800 so'rov ketadi — aksariyati "yangi narsa yo'q" javobi. Server behuda yuklanadi. 2 soniyalik kechikish bor — real chat uchun bu sezilarli.
WebSocket — boshqa yondashuv. Serverga bir marta ulanasiz, ulanish ochiq qoladi. Ali xabar yozganida — server o'zi Valiga "xabar keldi" deb yuboradi. So'rov kutish yo'q.
WebSocket nima?
WebSocket — brauzer va server o'rtasidagi doimiy, ikki tomonlama ulanish. Har ikki tomon ham istalgan vaqt xabar yuborishi mumkin — biri so'rov kutib o'tirmaydi.
Hayotiy o'xshatma
HTTP/fetch — xat yozish. Siz xat yozasiz → pochta orqali ketadi → server javob xat yozadi → pochta orqali keladi. Har safar yangi maktub, har safar pochta. Kechikish bor, pochta yuklanadi.
WebSocket — telefon qo'ng'irog'i. Bir marta qo'ng'iroq qilasiz → ikkalangiz ulanasiz → xohlaganingizda gaplasha olasiz → biri qo'yganda ulanish tugaydi. Doimiy kanal, minimal kechikish.
Ulanish yaratish
const ws = new WebSocket("wss://chat.example.com/socket");
// ↑
// wss:// — xavfsiz WebSocket (HTTPS dagi kabi)
// ws:// — xavfsiz bo'lmagan
WebSocket URL da http:// yoki https:// emas — ws:// yoki wss:// ishlatiladi.
To'rtta hodisa — ulanishning hayoti
WebSocket ulanishi to'rt hodisa orqali boshqariladi:
const ws = new WebSocket("wss://chat.example.com/socket");
// 1. Ulanish muvaffaqiyatli ochildi
ws.onopen = function() {
console.log("Server bilan ulandi!");
ws.send("Salom, server!"); // ← endi xabar yuborish mumkin
};
// 2. Server xabar yubordi
ws.onmessage = function(event) {
const malumot = JSON.parse(event.data);
console.log("Yangi xabar:", malumot);
};
// 3. Xato yuz berdi
ws.onerror = function(xato) {
console.error("WebSocket xatosi:", xato);
};
// 4. Ulanish yopildi
ws.onclose = function(event) {
console.log("Ulanish yopildi. Kod:", event.code);
};
Hayotiy o'xshatma — to'rt hodisa
Telefon qo'ng'irog'ini tasavvur qiling:
onopen— "Allo, eshitaman" — ulanish o'rnatildionmessage— narigi taraf gapirdi — xabar keldionerror— shovqin, ulanish buzildionclose— "xayr" deb qo'yildi — ulanish tugadi
Xabar yuborish — ws.send()
ws.send() — serverga xabar yuborish. Matn yoki ArrayBuffer yuboriladi. Ob'ekt yuborish uchun JSON.stringify:
ws.onopen = function() {
// Matn
ws.send("Salom!");
// Ob'ekt — JSON.stringify kerak
ws.send(JSON.stringify({
tur: "xabar",
matn: "Salom, Vali!",
vaqt: Date.now(),
}));
};
Server ham xuddi shunday yuboradi, brauzer onmessage da qabul qiladi.
Amaliy misol — chat
const ws = new WebSocket("wss://chat.example.com");
const ro_yxat = document.getElementById("xabarlar");
const maydon = document.getElementById("matn-maydon");
const tugma = document.getElementById("yuborish");
// Serverdan xabar keldi — ro'yxatga qo'shish
ws.onmessage = function(event) {
const xabar = JSON.parse(event.data);
const li = document.createElement("li");
li.textContent = `${xabar.kim}: ${xabar.matn}`;
ro_yxat.appendChild(li);
};
// Tugma bosildi — serverga yuborish
tugma.addEventListener("click", function() {
const matn = maydon.value.trim();
if (!matn || ws.readyState !== WebSocket.OPEN) return;
ws.send(JSON.stringify({ matn }));
maydon.value = "";
});
// Ulanish xatosi
ws.onerror = function() {
console.error("Ulanishda muammo — qayta urinib ko'ring");
};
readyState — ulanish holati
ws.readyState — WebSocket ning hozirgi holati. To'rtta qiymat:
0 — CONNECTING : ulanish o'rnatilmoqda
1 — OPEN : ulanish ochiq, yuborish mumkin
2 — CLOSING : yopilmoqda
3 — CLOSED : yopildi
Xabar yuborishdan oldin OPEN ekanini tekshirish muhim — CONNECTING holatda send() xato beradi.
if (ws.readyState === WebSocket.OPEN) {
ws.send("xabar");
} else {
console.warn("Ulanish hali ochiq emas");
}
Ulanishni yopish
ws.close(); // ← standart yopish (kod 1000 — normal)
ws.close(1000, "Ish tugadi"); // ← sabab bilan yopish
Sahifadan chiqilganda yoki component yo'qolganda — WebSocket yopilishi kerak. Aks holda ulanish "osilgan" holda qoladi.
// Sahifa yopilganda avtomatik yopilish
window.addEventListener("beforeunload", function() {
ws.close();
});
WebSocket qachon, Fetch qachon?
Bu savol doimo chiqadi. Ikkalasi ham server bilan muloqot uchun — lekin har xil holat uchun.
Fetch — bir martalik so'rov-javob. Foydalanuvchi ma'lumot so'radi → server javob berdi → tugadi. Login, mahsulot olish, forma yuborish.
WebSocket — doimiy ulanish, ikki tomonlama. Server ham istalgan vaqt xabar yuborishi kerak. Chat, o'yinlar, birga tahrirlash (Google Docs), birja narxlari, bildirishnomalar.
Hayotiy o'xshatma
Fetch — do'konga xaridor keldi, xarid qildi, ketdi. Har safar yangi tashrif.
WebSocket — do'kon xodimi ish joyida turadi, mijozlar kelganida xizmat ko'rsatadi. Doim tayyor.
Tez-tez uchraydigan xatolar
OPEN bo'lmasdan send() chaqirish:
const ws = new WebSocket("wss://...");
// ❌ — ws hali CONNECTING holatida, send() xato beradi
ws.send("salom");
// ✅ — onopen da yuborish
ws.onopen = function() {
ws.send("salom"); // ulanish ochilgandan keyin
};
onmessage da JSON parse xatosini ushlaslik:
// ❌ — server noto'g'ri JSON yuborsa — xato
ws.onmessage = function(event) {
const data = JSON.parse(event.data);
};
// ✅
ws.onmessage = function(event) {
try {
const data = JSON.parse(event.data);
// ...
} catch {
console.warn("Noto'g'ri JSON keldi:", event.data);
}
};
Ulanishni yopmaslik — xotira oqishi:
WebSocket yopilmasa — server tomonida ham ulanish "osilgan" qoladi. Foydalanuvchi sahifadan chiqsa yoki component o'chsa — ws.close() chaqirilishi kerak.
Xulosa
WebSocket — brauzer va server o'rtasidagi doimiy, ikki tomonlama ulanish. Server ham istalgan vaqt brauzerga xabar yuborishi mumkin.
To'rtta hodisa: onopen (ulandi), onmessage (xabar keldi), onerror (xato), onclose (yopildi).
ws.send(JSON.stringify(data)) — xabar yuborish. ws.close() — sahifadan chiqganda.
Real-time kerak bo'lganda — WebSocket. Bir martalik so'rov-javob uchun — Fetch.
Keyingi dars
52-dars: Intersection Observer — lazy loading uchun