WebSocketStream: Akışları WebSocket API ile entegre etme

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'si

WebSocket API WebSocket protokolü için bir JavaScript arayüzü sağlar, iki yönlü etkileşimli bir iletişim oturumuna başlamayı mümkün kılar. kullanıcının tarayıcısı ile sunucu arasında. Bu API ile sunucuya mesaj gönderebilir ve etkinliğe dayalı yanıtlar alabilirsiniz yanıt almak için sunucuyu yoklamaya gerek yoktur.

Streams API

Streams API JavaScript'in ağ üzerinden alınan veri parçalarının akışlarına programatik olarak erişmesine olanak tanır bunları istediğiniz gibi işleyebilirsiniz. Akışlar bağlamında önemli bir kavramdır ters basınç. Bu, tek bir akışın veya bir boru zincirinin okuma veya yazma hızını düzenler. Akışın kendisi veya boru zincirinin ilerleyen aşamalarındaki bir akış hâlâ kalabalık olduğunda daha fazla parça kabul etmeye hazır değilse uygun şekilde teslimi yavaşlatmak için zincirden geriye doğru bir sinyal gönderir.

Mevcut WebSocket API'siyle ilgili sorun

Alınan iletilere geri baskı uygulamak imkansız

Geçerli WebSocket API'sinde mesajlara tepki vermek şurada gerçekleşir: WebSocket.onmessage Sunucudan bir ileti alındığında bir EventHandler çağrılır.

Ağır miktarda veri işlemesi yapması gereken bir uygulamanız olduğunu varsayalım. yeni bir mesaj alırsınız. Akışı büyük olasılıkla aşağıdaki koda benzer şekilde ayarlarsınız. process() aramasının sonucunu await. Sonuçta başarılı olmalısı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. İletiler, process() yönteminin işleyebileceğinden daha hızlı ulaştığında oluşturma işlemi, bu mesajları arabelleğe alarak belleği kaplar. veya her iki nedenden dolayı yanıt vermemeye başlar.

Gönderilen iletilere karşı basınç uygulamak ergonomik değildir

Gönderilen iletilere karşı baskı uygulamak mümkündür ancak WebSocket.bufferedAmount verimsiz ve ergonomik olmayan özelliklere sahiptir. Bu salt okunur özellik, sıraya alınmış verilerin bayt sayısını döndürür. kullanarak WebSocket.send() ancak henüz ağa iletilmemiştir. Sıradaki tüm veriler gönderildikten sonra bu değer sıfırlanır. ancak WebSocket.send() adlı kişiyi aramaya devam ederseniz artmaya devam edecek.

WebSocketStream API nedir?

WebSocketStream API, var olmayan veya ergonomik olmayan karşı basınç sorununu ele alır. WebSocket API ile akışları entegre ederek 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:

  • Etkileşimi koruması gereken, yüksek bant genişliğine sahip WebSocket uygulamaları özellikle de video ve ekran paylaşımı.
  • Benzer şekilde, video yakalama ve tarayıcıda büyük miktarda veri üreten diğer uygulamalar yüklenmesi gereken bir dosyadır. Karşı basınç sayesinde istemci, verileri bellekte biriktirmek yerine veri üretmeyi durdurabilir.

Mevcut durum

Step Durum
1. Açıklayıcı oluşturun Tamamlandı
2. İlk spesifikasyon taslağını oluşturun Devam ediyor
3. Geri bildirim toplama tasarımı yineleyin Devam ediyor
4. Kaynak denemesi Tamamlandı
5. Başlat Başlatılmadı

WebSocketStream API'yi kullanma

Tanıtım örneği

WebSocketStream API vaat temellidir, bu da doğal bir şekilde işlem yapılmasını sağlar bir araya getirmektir. Yeni bir WebSocketStream oluşturup bunu WebSocket sunucusunun URL'sini ileterek başlarsınız. Sonra, bağlantının opened olmasını beklersiniz. Bu da ReadableStream ve/veya WritableStream.

ReadableStream.getReader() yöntemini kullanarak, nihayet ReadableStreamDefaultReader, Ardından read() veri akışı tamamlanana kadar, yani formda bir nesne döndürene kadar {value: undefined, done: true}

Buna uygun olarak, WritableStream.getWriter() yöntemini kullanarak, nihayet WritableStreamDefaultWriter, Ardından write() .

  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);
  }

Sızıntı

Söz edilen karşı baskı özelliğine ne olacak? Yukarıda da belirttiğim gibi, ek bir işlem yapmanıza gerek kalmadan "ücretsiz" olarak yararlanabilirsiniz. process() daha fazla zaman alırsa sonraki mesaj yalnızca ardışık düzen hazır olduğunda kullanılır. Benzer şekilde, WritableStreamDefaultWriter.write() adımı güvenli olduğu durumlarda işleme devam eder.

Gelişmiş örnekler

WebSocketStream'in ikinci bağımsız değişkeni, gelecekte uzatmaya olanak tanıyan bir seçenek çantasıdır. Şu anda tek seçenek protocols. her zaman WebSocket kurucusu için ikinci bağımsız değişken:

const chatWSS = new WebSocketStream(CHAT_URL, {protocols: ['chat', 'chatv2']});
const {protocol} = await chatWSS.opened;

Seçilen protocol ve potansiyel extensions sözlüğün bir parçası WebSocketStream.opened taahhüdüyle sunuluyor. Canlı bağlantıyla ilgili tüm bilgiler bu söz ile sağlanmaktadır. çünkü bağlantının başarısız olmasıyla ilgili değildir.

const {readable, writable, protocol, extensions} = await chatWSS.opened;

Kapalı WebSocketStream bağlantısı hakkında bilgi

Söz konusu WebSocket.onclose ve WebSocket.onerror etkinlik özellikleri artık WebSocketStream.closed sözü ile kullanılabilmektedir. Hatalı bir kapanış olması halinde vaat reddedilir. aksi takdirde, sunucu tarafından gönderilen koda ve nedene çözümlenir.

Olası tüm durum kodları ve anlamları şurada açıklanmıştır: CloseEvent durum kodlarının listesi.

const {code, reason} = await chatWSS.closed;

WebSocketStream bağlantısını kapatma

WebSocketStream, bir AbortController. Bu nedenle, bir AbortSignal WebSocketStream oluşturucusuna gönderilir.

const controller = new AbortController();
const wss = new WebSocketStream(URL, {signal: controller.signal});
setTimeout(() => controller.abort(), 1000);

Alternatif olarak, WebSocketStream.close() yöntemini de kullanabilirsiniz fakat asıl amacı, kod ve sunucuya gönderilme nedeni.

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ı uygulanamıyor. Gönderilen iletilere karşı baskı uygulamak mümkündür ancak WebSocket.bufferedAmount verimsiz ve ergonomik olmayan özelliklere sahiptir.

Ö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 iş başında görebilirsiniz. doğrudan Glitch'te paylaşabilirsiniz.

Geri bildirim

Chrome ekibi, WebSocketStream API deneyimleriniz hakkında bilgi almak istiyor.

Bize API tasarımı hakkında bilgi verin

API'de beklediğiniz gibi çalışmayan bir şey mi var? Yoksa fikrinizi uygulamak için ihtiyacınız olan eksik yöntemler veya özellikler mi var? Güvenlik modeliyle ilgili bir sorunuz veya yorumunuz mu var? İlgili GitHub deposunda bir spesifikasyon sorunu bildirin, veya düşüncelerinizi mevcut bir soruna ekleyebilirsiniz.

Uygulamayla ilgili bir sorunu bildirin

Chrome'un uygulanmasıyla ilgili bir hata buldunuz mu? Yoksa uygulama, spesifikasyondan farklı mı? new.crbug.com adresinden hata bildiriminde bulunun. Ürünün yeniden üretilmesine ilişkin mümkün olduğunca çok ayrıntı, basit talimatlar, 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 özelliklere öncelik vermesine yardımcı olur ve diğer tarayıcı tedarikçilerine, onları desteklemenin ne kadar önemli olduğunu gösteriyor.

Hashtag'i kullanarak @ChromiumDev hesabına tweet gönderin #WebSocketStream ve nerede ve nasıl kullandığınızı bize bildirin.

Faydalı bağlantılar

Teşekkür

WebSocketStream API, Adam Rice tarafından uygulanmıştır ve Yutaka Hirano Daan Mooij'in hero resmi Lansmanı kaldırın.