Geri basınç uygulayarak uygulamanızın WebSocket mesajlarıyla boğulmasını veya bir WebSocket sunucusunu mesajlarla 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, bir sunucuya mesaj gönderebilir ve sunucudan yanıt almak için anket yapmadan olaya dayalı yanıtlar alabilirsiniz.
Streams API
Streams API, JavaScript'in ağ üzerinden alınan veri parçaları akışlarına programatik olarak erişmesine ve bunları istediği gibi işlemesine olanak tanır. Akış bağlamında önemli bir kavram da geri basınçtır. Bu, tek bir akış veya boru zincirinin okuma ya da yazma hızını düzenlediği işlemdir. 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 ile ilgili sorun
Alınan mesajlara geri basınç uygulamak mümkün değildir.
Mevcut WebSocket API'de, bir mesaja tepki verme işlemi WebSocket.onmessage
içinde gerçekleşir. Bu, sunucudan bir mesaj alındığında çağrılan bir EventHandler
'tır.
Yeni bir mesaj alındığında yoğun veri işleme 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'nin sorunu, geri basınç uygulamanın mümkün olmamasıdır.
Mesajlar, process()
yönteminin işleyebileceğinden daha hızlı geldiğinde oluşturma işlemi ya bu mesajları arabelleğe alarak belleği doldurur, ya% 100 CPU kullanımı nedeniyle yanıt vermez hale gelir ya da her ikisini birden yapar.
Gönderilen mesajlara geri 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, geri basıncın ek ücret ödemeden "ücretsiz" olarak uygulanabileceği anlamına gelir.
WebSocketStream API için önerilen kullanım alanları
Bu API'yi kullanabilen sitelere örnek olarak şunlar verilebilir:
- Özellikle video ve ekran paylaşımı olmak üzere etkileşimi koruması gereken yüksek bant genişliğine sahip WebSocket uygulamaları.
- Benzer şekilde, tarayıcıda çok fazla veri oluşturan ve sunucunun yüklemesi gereken diğer uygulamalar da bu kapsamdadır. Geri basınç sayesinde istemci, verileri bellekte biriktirmek yerine veri üretmeyi durdurabilir.
Mevcut durum
Step | Durum |
---|---|
1. Açıklayıcı oluşturma | Tamamlandı |
2. Spesifikasyonun ilk taslağını oluşturma | Devam ediyor |
3. Geri bildirim toplayın ve tasarımda iterasyon yapın | Devam ediyor |
4. Kaynak denemesi | Tamamlandı |
5. Başlat | Başlatılmadı |
WebSocketStream API'yi kullanma
WebSocketStream API'si, modern JavaScript dünyasında doğal bir şekilde kullanılabilmesi için söze dayalı bir API'dir.
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()
metodunu çağırarak bir ReadableStreamDefaultReader
elde edersiniz. Bu read()
, akış tamamlanana kadar yani {value: undefined, done: true}
biçiminde bir nesne döndürene kadar veri alabilir.
Bu nedenle, WritableStream.getWriter()
yöntemini çağırarak bir WritableStreamDefaultWriter
elde edersiniz. Bu write()
veri ekleyebilirsiniz.
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 verilen geri basınç özelliği 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 uzantıya izin vermek için bir seçenek paketidir.
Tek seçenek protocols
'tür. Bu seçenek, WebSocket oluşturucusunun 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 olası extensions
, WebSocketStream.opened
vaadi aracılığıyla kullanılabilen 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 edilebilen bilgiler artık WebSocketStream.closed
promise aracılığıyla kullanılabilir.
Sözleşme, temiz olmayan bir kapatma durumunda reddeder. 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ı, sunucuya gönderilecek kodu ve 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 basınç uygulamak mümkün değildir.
Gönderilen mesajlara geri basınç uygulamak mümkündür ancak WebSocket.bufferedAmount
mülkünü yoklamayı gerektirir. Bu işlem hem verimsiz hem de ergonomik değildir.
Özellik algılama
WebSocketStream API'nin desteklenip desteklenmediğini kontrol etmek için:
if ('WebSocketStream' in window) {
// `WebSocketStream` is supported!
}
Demo
Desteklenen tarayıcılarda, WebSocketStream API'yi yerleşik iFrame'de veya doğrudan Glitch'te çalışırken görebilirsiniz.
Geri bildirim
Chrome Ekibi, WebSocketStream API ile ilgili deneyimlerinizi öğrenmek istiyor.
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 sorunuz veya yorumunuz mu var? İlgili GitHub deposunda özellik sorunu oluşturun veya mevcut bir soruna düşüncelerinizi ekleyin.
Uygulamayla ilgili sorunları bildirme
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, hataları hızlı ve kolay bir şekilde paylaşmak için idealdir.
API'yi destekleme
WebSocketStream API'yi kullanmayı planlıyor musunuz? Herkese açık desteğiniz, Chrome ekibinin özelliklere öncelik vermesine yardımcı olur ve diğer tarayıcı tedarikçi firmalarına bu özellikleri desteklemenin ne kadar önemli 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çıklama
- WebSocketStream API Demo | WebSocketStream API Demo kaynağı
- İzleme hatası
- ChromeStatus.com girişi
- Blink Bileşeni:
Blink>Network>WebSockets
Teşekkür ederiz
WebSocketStream API'si Adam Rice ve Yutaka Hirano tarafından uygulanmıştır.