WebSocketStream: WebSocket API के साथ स्ट्रीम इंटिग्रेट करना

अपने ऐप्लिकेशन को WebSocket मैसेज में डूबने से रोकें या बैकप्रेशर लागू करके WebSocket सर्वर को मैसेज से भरें.

थॉमस स्टाइनर
थॉमस स्टाइनर

बैकग्राउंड

WebSocket एपीआई

WebSocket API WebSocket प्रोटोकॉल के लिए एक JavaScript इंटरफ़ेस उपलब्ध कराता है. इससे उपयोगकर्ता के ब्राउज़र और सर्वर के बीच, दोतरफ़ा इंटरैक्टिव कम्यूनिकेशन सेशन खोला जा सकता है. इस एपीआई की मदद से, सर्वर को मैसेज भेजे जा सकते हैं और सर्वर को जवाब के लिए पोल कराए बिना ही इवेंट-ड्रिवन जवाब मिल सकते हैं.

Streams API

Streams API, JavaScript को नेटवर्क से मिले डेटा हिस्से की स्ट्रीम को प्रोग्राम के हिसाब से ऐक्सेस करने और उन्हें मनमुताबिक प्रोसेस करने की अनुमति देता है. स्ट्रीम के संदर्भ में एक अहम कॉन्सेप्ट है, बैकप्रेशर. यह ऐसी प्रक्रिया है जिससे एक ही स्ट्रीम या पाइप चेन, पढ़ने या लिखने की स्पीड को कंट्रोल करती है. जब खुद स्ट्रीम या बाद में पाइप चेन में कोई स्ट्रीम अभी भी व्यस्त होती है और ज़्यादा हिस्सों को स्वीकार करने के लिए तैयार नहीं होती, तो डिलीवरी को धीमा करने के लिए, यह चेन को पीछे की ओर सिग्नल भेजता है.

मौजूदा WebSocket API से जुड़ी समस्या

मैसेज पाने वाले लोगों के लिए, बैकप्रेशर लागू नहीं किया जा सकता

मौजूदा WebSocket API से, किसी मैसेज पर प्रतिक्रिया WebSocket.onmessage में होती है. सर्वर से मैसेज मिलने पर, EventHandler को कॉल किया जाता है.

मान लें कि आपके पास एक ऐसा ऐप्लिकेशन है जो कोई नया मैसेज मिलने पर डेटा क्रंच करने की कार्रवाई करता है. आप शायद नीचे दिए गए कोड की तरह ही फ़्लो सेट अप करेंगे और process() कॉल के नतीजे await हुए हैं, इसलिए आपको बेहतर होना चाहिए, है न?

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

गलत! मौजूदा WebSocket API में समस्या यह है कि बैकप्रेशर लागू करने का कोई तरीका मौजूद नहीं है. जब मैसेज process() से ज़्यादा जल्दी आते हैं, तो उन्हें रेंडर करने की प्रोसेस, उन मैसेज को बफ़र करके मेमोरी भर जाएगी या 100% सीपीयू (CPU) के इस्तेमाल की वजह से या दोनों तरीकों से काम नहीं करेगी.

भेजे गए मैसेज पर बैकप्रेशर लागू करना आसान नहीं है

भेजे गए मैसेज पर बैकप्रेशर लागू किया जा सकता है, लेकिन इसमें WebSocket.bufferedAmount प्रॉपर्टी को पोल कराना शामिल है, जो कारगर नहीं है और एर्गोनॉमिक नहीं है. रीड ओनली प्रॉपर्टी से, उन बाइट डेटा की जानकारी मिलती है जो WebSocket.send() पर कॉल का इस्तेमाल करके सूची में बनाए गए हैं, लेकिन अभी तक नेटवर्क पर ट्रांसमिट नहीं किए गए हैं. पूरा डेटा भेजे जाने के बाद, यह वैल्यू शून्य पर रीसेट हो जाती है. लेकिन अगर आप WebSocket.send() को कॉल करते रहेंगे, तो यह बढ़ता रहेगा.

WebSocketStream API क्या है?

WebSocketStream API, गैर-मौजूद या गैर-एर्गोनॉमिक बैकप्रेशर की समस्या से निपटने के लिए, WebSocket API के साथ स्ट्रीम इंटिग्रेट करता है. इसका मतलब है कि बैकप्रेशर को बिना किसी अतिरिक्त शुल्क के "मुफ़्त" में लागू किया जा सकता है.

WebSocketStream API के लिए, इस्तेमाल के सुझाए गए उदाहरण

इस एपीआई का इस्तेमाल करने वाली साइटों के उदाहरण:

  • उच्च बैंडविड्थ वाले WebSocket ऐप्लिकेशन, जिन्हें खास तौर पर वीडियो और स्क्रीन शेयर करने के लिए, इंटरैक्टिविटी बनाए रखने की ज़रूरत होती है.
  • इसी तरह, वीडियो कैप्चर और अन्य ऐप्लिकेशन जो ब्राउज़र में बहुत सारा डेटा जनरेट करते हैं, जिन्हें सर्वर पर अपलोड करने की ज़रूरत होती है. बैकप्रेशर की मदद से क्लाइंट, मेमोरी में डेटा इकट्ठा करने के बजाय डेटा बनाना बंद कर सकता है.

मौजूदा स्थिति

| चरण | स्थिति | | ------------------------------------------ | ---------------------------- | | 1. जानकारी देने वाला फ़ॉर्मैट बनाएं | [पूरी जानकारी] | | 2. स्पेसिफ़िकेशन का शुरुआती ड्राफ़्ट बनाएं | [जारी है][खास जानकारी] | | 3. सुझाव इकट्ठा करना और डिज़ाइन को बेहतर बनाना | [जानकारी जारी है](#फ़ीडबैक) | | 4. शुरुआत की जगह का ट्रायल | [पूरा][ot] | | 5. लॉन्च करें | शुरू नहीं किया है |

WebSocketStream API को इस्तेमाल करने का तरीका

शुरुआती उदाहरण

WebSocketStream API, वादों पर आधारित है. इसलिए, JavaScript की मौजूदा दुनिया में ऐसा करना स्वाभाविक है. सबसे पहले एक नया WebSocketStream बनाएं और उसे WebSocket सर्वर का यूआरएल पास करें. इसके बाद, आपको कनेक्शन के opened होने का इंतज़ार करना होगा, जिसकी वजह से ReadableStream और/या WritableStream दिखेगा.

ReadableStream.getReader() तरीके का इस्तेमाल करने पर, आपको एक ReadableStreamDefaultReader मिलता है. इससे, स्ट्रीम पूरी होने तक read() से डेटा लिया जा सकता है. इसका मतलब है कि फ़ॉर्म का कोई ऑब्जेक्ट मिलने तक{value: undefined, done: true}.

इसी तरह, WritableStream.getWriter() तरीका कॉल करने पर, आपको एक WritableStreamDefaultWriter डेटा मिलता है, जिसका इस्तेमाल करने के बाद, 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);
  }

पीठ दर्द

बैकप्रेशर सुविधा के बारे में क्या ख्याल है? जैसा कि मैंने ऊपर लिखा था, यह ऑफ़र "मुफ़्त" में उपलब्ध है. आपको कुछ और करने की ज़रूरत नहीं है. अगर process() को ज़्यादा समय लगता है, तो पाइपलाइन तैयार होने के बाद ही अगला मैसेज भेजा जाएगा. इसी तरह, WritableStreamDefaultWriter.write() चरण सिर्फ़ तब आगे चलेगा, जब ऐसा करना सुरक्षित हो.

बेहतर सेटिंग के उदाहरण

WebSocketStream का दूसरा आर्ग्युमेंट, एक विकल्प बैग है जो आने वाले समय में एक्सटेंशन इस्तेमाल करने की अनुमति देता है. फ़िलहाल, protocols ही विकल्प है, जो WebSocket कंस्ट्रक्टर के साथ दूसरे आर्ग्युमेंट की तरह ही काम करता है:

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

चुने गए protocol और संभावित extensions, शब्दकोश का हिस्सा हैं जो WebSocketStream.opened प्रॉमिस के ज़रिए उपलब्ध है. लाइव कनेक्शन के बारे में सारी जानकारी इस प्रॉमिस से दी गई होती है, क्योंकि कनेक्शन के पूरा न होने पर यह काम का नहीं होता.

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

बंद WebSocketStream कनेक्शन के बारे में जानकारी

WebSocket API में WebSocket.onclose और WebSocket.onerror इवेंट से मिली जानकारी अब WebSocketStream.closed प्रॉमिस के ज़रिए उपलब्ध है. गड़बड़ी होने पर प्रॉमिस अस्वीकार हो जाता है. अगर ऐसा नहीं होता है, तो प्रॉमिस उस कोड और वजह से डिसकनेक्ट हो जाता है जो सर्वर से भेजी गई है.

सभी संभावित स्टेटस कोड और उनके मतलब के बारे में, CloseEvent स्टेटस कोड की सूची में बताया गया है.

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

WebSocketStream कनेक्शन बंद करना

WebSocketStream को AbortController की मदद से बंद किया जा सकता है. इसलिए, WebSocketStream कंस्ट्रक्टर को AbortSignal पास करें.

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

विकल्प के तौर पर, WebSocketStream.close() तरीके का भी इस्तेमाल किया जा सकता है, लेकिन इसका मुख्य मकसद सर्वर पर भेजे गए कोड और वजह को तय करने की अनुमति देना होता है.

wss.close({code: 4000, reason: 'Game over'});

प्रोग्रेसिव एन्हैंसमेंट और इंटरऑपरेबिलिटी

फ़िलहाल, सिर्फ़ Chrome ऐसा ब्राउज़र है जिसने WebSocketStream एपीआई लागू किया है. क्लासिक WebSocket API के साथ इंटरऑपरेबिलिटी के लिए, मिले हुए मैसेज पर बैकप्रेस लागू नहीं किया जा सकता. भेजे गए मैसेज पर बैकप्रेशर लागू किया जा सकता है, लेकिन इसमें WebSocket.bufferedAmount प्रॉपर्टी को पोल कराना शामिल है, जो कारगर नहीं है और एर्गोनॉमिक नहीं है.

सुविधा का पता लगाना

यह जांचने के लिए कि क्या WebSocketStream API काम करता है या नहीं, इसका इस्तेमाल करें:

if ('WebSocketStream' in window) {
  // `WebSocketStream` is supported!
}

डेमो

इसके साथ काम करने वाले ब्राउज़र पर, एम्बेड किए गए iframe में या सीधे Glitch पर जाकर, WebSocketStream एपीआई को काम करते हुए देखा जा सकता है.

सुझाव/राय दें या शिकायत करें

Chrome टीम, WebSocketStream API के इस्तेमाल से जुड़े आपके अनुभव के बारे में जानना चाहती है.

हमें एपीआई डिज़ाइन के बारे में बताएं

क्या इस एपीआई में कोई ऐसी गड़बड़ी है जो आपकी उम्मीद के मुताबिक काम नहीं करती? या फिर अपना आइडिया लागू करने के लिए तरीके या प्रॉपर्टी मौजूद नहीं हैं? क्या आपके पास सुरक्षा मॉडल पर कोई सवाल या टिप्पणी है? संबंधित GitHub रिपो के बारे में कोई खास समस्या दर्ज करें, या किसी मौजूदा समस्या के बारे में अपने विचार जोड़ें.

लागू करने से जुड़ी समस्या की शिकायत करें

क्या आपको Chrome को लागू करने के दौरान कोई गड़बड़ी मिली? या फिर लागू करने का तरीका खास जानकारी से अलग है? new.crbug.com पर जाकर गड़बड़ी की शिकायत करें. ज़्यादा से ज़्यादा जानकारी, फिर से बनाने के आसान निर्देश, और कॉम्पोनेंट बॉक्स में Blink>Network>WebSockets डालें. Glitch दोबारा बनाने का तरीका जल्दी और आसानी से शेयर करने के लिए, अच्छी तरह काम करता है.

एपीआई की सुविधा का इस्तेमाल करें

क्या आपको WebSocketStream API इस्तेमाल करना है? आपके सार्वजनिक समर्थन से Chrome टीम को सुविधाओं को प्राथमिकता देने में मदद मिलती है और यह अन्य ब्राउज़र वेंडर को दिखाता है कि उनकी सहायता करना कितना ज़रूरी है.

हैशटैग का इस्तेमाल करके @ChromiumDev को एक ट्वीट भेजें #WebSocketStream और हमें बताएं कि इसका इस्तेमाल कहां और कैसे किया जा रहा है.

मददगार लिंक

स्वीकारें

WebSocketStream API को Adam Rice और Yutaka Hirano ने लागू किया था. Unस्प्लैश पर डेन मूइज की हीरो इमेज.