Ters basınç uygulayarak uygulamanızın WebSocket mesajlarında boğulmasını veya bir WebSocket sunucusunu iletilerle doldurmasını önleyin.
Arka plan
WebSocket API, WebSocket protokolü için bir JavaScript arayüzü sağlar. Bu arayüz, kullanıcının tarayıcısı ile sunucu arasında iki yönlü etkileşimli bir iletişim oturumu açmayı mümkün kılar. Bu API ile sunucuya mesaj gönderebilir ve sunucuyu yanıt almak için yoklamadan etkinliğe dayalı yanıtlar alabilirsiniz.
Streams API
Streams API, JavaScript'in ağ üzerinden alınan veri parçası akışlarına programatik olarak erişmesine ve bunları istenen şekilde işlemesine olanak tanır. Akışlar bağlamında önemli bir kavram geri bastırmadır. Bu, okuma veya yazma hızının tek bir akış ya da boru zinciriyle düzenlenmesidir. Akış veya ardışık düzen zincirinin sonraki bir yayını hâlâ meşgulse ve daha fazla parçayı kabul etmeye hazır değilse yayın, zincir boyunca geriye doğru bir sinyal göndererek yayını uygun şekilde yavaşlatır.
Mevcut WebSocket API'sindeki sorun
Alınan mesajlara geri basınç uygulamak mümkün değildir.
Mevcut WebSocket API ile bir iletiye tepki, WebSocket.onmessage
içinde gerçekleşir. Bu da sunucudan bir ileti alındığında EventHandler
olarak anılır.
Her yeni mesaj alındığında ağır veri işlemesi işlemleri yapması gereken bir uygulamanız olduğunu varsayalım.
Akışınızı büyük olasılıkla aşağıdaki koda benzer şekilde ayarlarsınız. process()
çağrısının sonucunu await
ettiğiniz için sorun yaşamazsınız, değil mi?
// A heavy data crunching operation.
const process = async (data) => {
return new Promise((resolve) => {
window.setTimeout(() => {
console.log('WebSocket message processed:', data);
return resolve('done');
}, 1000);
});
};
webSocket.onmessage = async (event) => {
const data = event.data;
// Await the result of the processing step in the message handler.
await process(data);
};
Yanlış! Mevcut WebSocket API'deki sorun, karşı basınç uygulamanın bir yolunun olmamasıdır.
Mesajlar, process()
yönteminin işleyebileceğinden daha hızlı geldiğinde oluşturma işlemi bu mesajları arabelleğe alarak belleği doldurur, %100 CPU kullanımı nedeniyle yanıt vermez veya her ikisini birden yapar.
Gönderilen iletilere karşı basınç uygulamak ergonomik değildir
Gönderilen mesajlara geri basınç uygulamak mümkündür ancak WebSocket.bufferedAmount
mülkünü yoklamak gerekir. Bu işlem hem verimsiz hem de ergonomik değildir.
Bu salt okunur mülk, WebSocket.send()
çağrıları kullanılarak sıraya eklenen ancak henüz ağa aktarılmayan bayt sayısı döndürür.
Bu değer, sıraya alınan tüm veriler gönderildikten sonra sıfıra sıfırlanır ancak WebSocket.send()
çağrısını yapmaya devam ederseniz değer artmaya devam eder.
WebSocketStream API nedir?
WebSocketStream API, akışları WebSocket API ile entegre ederek geri basınç olmaması veya ergonomik olmaması sorununu çözer. Bu, baskının herhangi bir ek maliyet olmadan "ücretsiz" olarak uygulanabileceği anlamına gelir.
WebSocketStream API için önerilen kullanım alanları
Bu API'yi kullanılabilecek sitelere örnek olarak şunlar verilebilir:
- Özellikle video ve ekran paylaşımında, etkileşimi sürdürmesi gereken yüksek bant genişliğine sahip WebSocket uygulamaları.
- Benzer şekilde, video yakalama ve tarayıcıda büyük miktarda veri üreten ve sunucuya yüklenmesi gereken diğer uygulamalar. Karşı basınç sayesinde istemci, verileri bellekte biriktirmek yerine veri üretmeyi durdurabilir.
Mevcut durum
Step | Durum |
---|---|
1. Açıklayıcı oluşturun | Tamamlandı |
2. Spesifikasyonun ilk taslağını oluşturma | Devam ediyor |
3. Geri bildirim alma ve tasarım üzerinde yineleme | Devam ediyor |
4. Kaynak denemesi | Tamamlandı |
5. Başlat | Başlatılmadı |
WebSocketStream API'yi kullanma
WebSocketStream API vaat temellidir. Bu nedenle, modern JavaScript dünyasında bu API'yle uğraşmak doğal bir deneyim haline gelir.
Yeni bir WebSocketStream
oluşturarak ve ona WebSocket sunucusunun URL'sini ileterek başlarsınız.
Ardından, bağlantının opened
olmasını bekleyin. Bu, ReadableStream
ve/veya WritableStream
ile sonuçlanır.
ReadableStream.getReader()
yöntemini çağırarak nihayet bir ReadableStreamDefaultReader
elde edersiniz. Daha sonra bu verileri read()
, akış tamamlanana kadar, yani {value: undefined, done: true}
formunun bir nesnesini döndürene kadar kullanabilirsiniz.
Buna göre, WritableStream.getWriter()
yöntemini çağırarak nihayet bir WritableStreamDefaultWriter
elde edersiniz. Daha sonra bunu write()
yapabilirsiniz.
const wss = new WebSocketStream(WSS_URL);
const {readable, writable} = await wss.opened;
const reader = readable.getReader();
const writer = writable.getWriter();
while (true) {
const {value, done} = await reader.read();
if (done) {
break;
}
const result = await process(value);
await writer.write(result);
}
Geri basınç
Söz edilen karşı basınç özelliğine ne olacak?
"Ücretsiz" olarak alırsınız, ek işlem yapmanız gerekmez.
process()
daha fazla zaman alırsa bir sonraki mesaj yalnızca ardışık düzen hazır olduğunda tüketilir.
Benzer şekilde, WritableStreamDefaultWriter.write()
adımı da yalnızca güvenli olduğunda devam eder.
İleri düzey örnekler
WebSocketStream'in ikinci bağımsız değişkeni, gelecekte uzatmaya olanak tanıyan bir seçenek çantasıdır.
Yalnızca protocols
seçeneği kullanılabilir. Bu seçenek, WebSocket kurucusunun ikinci bağımsız değişkeni ile aynı şekilde çalışır:
const chatWSS = new WebSocketStream(CHAT_URL, {protocols: ['chat', 'chatv2']});
const {protocol} = await chatWSS.opened;
Seçilen protocol
ve potansiyel extensions
, WebSocketStream.opened
taahhüdüyle sunulan sözlüğün bir parçasıdır.
Bağlantının başarısız olması önemli olmadığından, canlı bağlantıyla ilgili tüm bilgiler bu taahhüt kapsamında sağlanır.
const {readable, writable, protocol, extensions} = await chatWSS.opened;
Kapalı WebSocketStream bağlantısı hakkında bilgi
WebSocket API'deki WebSocket.onclose
ve WebSocket.onerror
etkinliklerinden elde edilen bilgilere artık WebSocketStream.closed
sözü ile ulaşabilirsiniz.
Vaat, açık olmayan bir kapatma durumunda reddedilir. Aksi takdirde, sunucu tarafından gönderilen koda ve nedene çözümlenir.
Olası tüm durum kodları ve anlamları, CloseEvent
durum kodları listesinde açıklanmıştır.
const {code, reason} = await chatWSS.closed;
WebSocketStream bağlantısını kapatma
WebSocketStream, AbortController
ile kapatılabilir.
Bu nedenle, WebSocketStream
oluşturucuya bir AbortSignal
iletin.
const controller = new AbortController();
const wss = new WebSocketStream(URL, {signal: controller.signal});
setTimeout(() => controller.abort(), 1000);
Alternatif olarak WebSocketStream.close()
yöntemini de kullanabilirsiniz ancak bu yöntemin asıl amacı, kodu ve sunucuya gönderilen nedeni belirtmenize izin vermektir.
wss.close({code: 4000, reason: 'Game over'});
Progresif geliştirme ve birlikte çalışabilirlik
Chrome, şu anda WebSocketStream API'yi uygulayan tek tarayıcıdır.
Klasik WebSocket API ile birlikte çalışabilirlik için alınan mesajlara geri baskı uygulamak mümkün değildir.
Gönderilen mesajlara geri basınç uygulamak mümkündür ancak WebSocket.bufferedAmount
mülkünü yoklamak gerekir. Bu işlem hem verimsiz hem de ergonomik değildir.
Özellik algılama
WebSocketStream API'nin desteklenip desteklenmediğini kontrol etmek için şunu kullanın:
if ('WebSocketStream' in window) {
// `WebSocketStream` is supported!
}
Demo
Desteklenen tarayıcılarda WebSocketStream API'yi yerleşik iframe'de veya doğrudan Glitch'te görebilirsiniz.
Geri bildirim
Chrome Ekibi, WebSocketStream API ile ilgili deneyimlerinizi öğrenmek istiyor.
Bize API tasarımı hakkında bilgi verin
API ile ilgili olarak beklediğiniz gibi çalışmayan bir şey var mı? Yoksa fikrinizi uygulamak için ihtiyaç duyduğunuz yöntemler veya özellikler eksik mi? Güvenlik modeliyle ilgili bir sorunuz veya yorumunuz mu var? İlgili GitHub deposunda spesifikasyon sorunu oluşturun veya mevcut bir soruna düşüncelerinizi ekleyin.
Uygulamayla ilgili bir sorunu bildirin
Chrome'un uygulamasında bir hata mı buldunuz?
Yoksa uygulama, spesifikasyondan farklı mı?
new.crbug.com adresinden hata kaydı oluşturun. Mümkün olduğunca fazla ayrıntı ekleyin, hatayı yeniden oluşturmayla ilgili basit talimatlar verin ve Bileşenler kutusuna Blink>Network>WebSockets
yazın.
Glitch, yeniden oluşturma vakalarını hızlı ve kolay bir şekilde paylaşmak için idealdir.
API'ye desteğinizi gösterin
WebSocketStream API'yi kullanmayı planlıyor musunuz? Herkese açık desteğiniz, Chrome ekibinin özellikleri önceliklendirmesine yardımcı olur ve diğer tarayıcı tedarikçilerine bunları desteklemenin ne kadar kritik olduğunu gösterir.
#WebSocketStream
hashtag'ini kullanarak @ChromiumDev hesabına tweet gönderin ve bu özelliği nerede ve nasıl kullandığınızı bize bildirin.
Faydalı bağlantılar
- Herkese açık açıklayıcı
- WebSocketStream API Demo | WebSocketStream API Demo kaynağı
- İzleme hatası
- ChromeStatus.com girişi
- Blink Bileşeni:
Blink>Network>WebSockets
Teşekkür
WebSocketStream API, Adam Rice ve Yutaka Hirano tarafından uygulanmıştır.