स्ट्रीम—खास गाइड

Streams API की मदद से, स्ट्रीम में पढ़ने लायक, लिखने लायक, और पूरी स्ट्रीम में बदलाव करने का तरीका जानें.

Streams API की मदद से, नेटवर्क से मिलने वाले डेटा की स्ट्रीम को प्रोग्राम के हिसाब से ऐक्सेस किया जा सकता है या स्थानीय रूप से किसी भी अन्य तरीके से बनाया गया हो और उन्हें JavaScript की मदद से प्रोसेस किया जा सकता है. स्ट्रीमिंग में ऐसे संसाधन का डेटा अलग-अलग होना शामिल है जिसे आप पाना, भेजना या पूरी तरह बदलना चाहते हैं इन टुकड़ों को छोटे-छोटे टुकड़ों में बांटें और फिर इन हिस्सों को एक-एक करके प्रोसेस करें. वीडियो स्ट्रीम करते समय ब्राउज़र किसी भी तरह तब भी कर सकते हैं, जब आपको वेबपेजों पर HTML या वीडियो जैसे एसेट मिल रहे हों, तो साल 2015 में स्ट्रीम के शुरू होने से पहले, fetch से पहले यह सुविधा JavaScript के लिए उपलब्ध नहीं थी.

पहले, अगर आपको किसी तरह के संसाधन (जैसे, कोई वीडियो या टेक्स्ट फ़ाइल वगैरह) को प्रोसेस करना था, तो आपको पूरी फ़ाइल डाउनलोड करनी होगी, इसके सही फ़ॉर्मैट में डीसीरियलाइज़ होने तक इंतज़ार करना होगा, और फिर उसे प्रोसेस करता है. इनके लिए स्ट्रीम उपलब्ध होने पर JavaScript, ये सभी बदल जाते हैं. अब JavaScript की मदद से, रॉ डेटा को इस तरह प्रोसेस किया जा सकता है बफ़र, स्ट्रिंग या BLOB जनरेट किए बिना, क्लाइंट के लिए उपलब्ध हो जाता है. इससे इस्तेमाल के कई उदाहरण अनलॉक हो जाते हैं, जिनमें से कुछ नीचे दिए गए हैं:

  • वीडियो इफ़ेक्ट: इफ़ेक्ट लागू करने वाली ट्रांसफ़ॉर्म स्ट्रीम की मदद से, आसानी से पढ़ी जा सकने वाली वीडियो स्ट्रीम को सिंक करना रीयल टाइम में.
  • डेटा (डी)कंप्रेस करना: किसी फ़ाइल स्ट्रीम को चुनिंदा तरीके से बदलने वाली स्ट्रीम से पाइप करना (de)कंप्रेस करता है.
  • इमेज डिकोडिंग: एचटीटीपी रिस्पॉन्स स्ट्रीम को ट्रांसफ़ॉर्मेशन स्ट्रीम से पाइप करना जो बाइट डीकोड करती हो और फिर बिटमैप डेटा को PNG में बदलने वाली किसी अन्य स्ट्रीम के ज़रिए ट्रांसफ़ॉर्म करता है. अगर आपने किसी सर्विस वर्कर के fetch हैंडलर के अंदर इंस्टॉल किया जाता है, तो यह आपको पारदर्शिता के साथ पॉलीफ़िल की अनुमति देता है. AVIF जैसे नए इमेज फ़ॉर्मैट नहीं हैं.

ब्राउज़र समर्थन

ReadableStream और WritableStream

ब्राउज़र सहायता

  • Chrome: 43. अभी तक किसी भी व्यक्ति ने चेक इन नहीं किया है
  • एज: 14. अभी तक किसी भी व्यक्ति ने चेक इन नहीं किया है
  • Firefox: 65. अभी तक किसी भी व्यक्ति ने चेक इन नहीं किया है
  • Safari: 10.1. अभी तक किसी भी व्यक्ति ने चेक इन नहीं किया है

सोर्स

TransformStream

ब्राउज़र सहायता

  • Chrome: 67. अभी तक किसी भी व्यक्ति ने चेक इन नहीं किया है
  • एज: 79. अभी तक किसी भी व्यक्ति ने चेक इन नहीं किया है
  • Firefox: 102. अभी तक किसी भी व्यक्ति ने चेक इन नहीं किया है
  • Safari: 14.1. अभी तक किसी भी व्यक्ति ने चेक इन नहीं किया है

सोर्स

मुख्य सिद्धांत

अलग-अलग तरह की लाइव स्ट्रीम के बारे में जानने से पहले, चलिए कुछ अहम कॉन्सेप्ट के बारे में जानते हैं.

चंक

डेटा का ग्रुप, डेटा का एक हिस्सा होता है. इसे किसी स्ट्रीम के लिए लिखा जाता है या उससे पढ़ा जाता है. यह कोई भी टाइप; स्ट्रीम में अलग-अलग तरह के कई हिस्से हो सकते हैं. ज़्यादातर मामलों में, चुना गया हिस्सा सबसे ज़्यादा ऐटमिक नहीं होता की इकाई हो सकती है. उदाहरण के लिए, एक बाइट स्ट्रीम में 16 वाले हिस्से हो सकते हैं सिंगल बाइट के बजाय, Uint8Array यूनिट के लिए KiB में बदलाव किए जा सकते हैं.

पढ़ने लायक स्ट्रीम

आसानी से पढ़ी जा सकने वाली स्ट्रीम, डेटा का ऐसा सोर्स होती है जिसे पढ़ा जा सकता है. दूसरे शब्दों में, डेटा आउट हो सकते हैं. सीधे तौर पर, पढ़ने लायक स्ट्रीम, ReadableStream का एक इंस्टेंस है क्लास.

राइटेबल स्ट्रीम

राइटेबल स्ट्रीम, डेटा के लिए एक डेस्टिनेशन दिखाती है, जिसमें डेटा लिखा जा सकता है. दूसरे शब्दों में, डेटा लिखने लायक स्ट्रीम में जाता है. सीधे तौर पर, लिखने लायक स्ट्रीम एक उदाहरण है, WritableStream क्लास.

स्ट्रीम को बदलें

ट्रांसफ़ॉर्म स्ट्रीम में स्ट्रीम का जोड़ा होता है: लिखने वाली एक स्ट्रीम, जिसे इसके लिखने वाले हिस्से के तौर पर जाना जाता है. और एक पठनीय स्ट्रीम, जिसे इसके पठनीय पक्ष के रूप में जाना जाता है. इसके लिए, वास्तविक दुनिया का एक प्रतीक हो सकता है एक साथ कई अनुवादक जो तुरंत एक भाषा से दूसरी भाषा में अनुवाद करते हैं. स्ट्रीम को बदलने के लिए खास तौर पर, से पढ़ने के लिए उपलब्ध किया जा रहा है, जिसका इस्तेमाल किया जा सकता है. पढ़ने लायक हिस्सा. सीधे तौर पर, writable प्रॉपर्टी और readable प्रॉपर्टी वाला कोई भी ऑब्जेक्ट काम कर सकता है की तरह है. हालांकि, स्टैंडर्ड TransformStream क्लास से बनाना आसान हो जाता है जिससे कि आपका जोड़ा सही तरह से आपस में उलझ जाए.

पाइप चेन

स्ट्रीम का इस्तेमाल मुख्य रूप से, एक-दूसरे से पाइप करके किया जाता है. आसानी से पढ़ी जा सकने वाली स्ट्रीम को सीधे पाइप किया जा सकता है किसी ऐसी स्ट्रीम में जोड़ना जिसे पढ़ने लायक स्ट्रीम के pipeTo() तरीके का इस्तेमाल किया गया हो या उसे किसी एक स्ट्रीम से पाइप किया जा सकता हो या ज़्यादा फ़ॉर्मैट में स्ट्रीम करने का विकल्प चुनें. इसके लिए, पढ़ने लायक स्ट्रीम के pipeThrough() तरीके का इस्तेमाल करें. का सेट इस तरह से एक साथ पाइप होने वाली स्ट्रीम को पाइप चेन कहा जाता है.

बैकप्रेशर

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

टीइंग

आसानी से पढ़ी जा सकने वाली स्ट्रीम का नाम (इसका नाम अपरकेस 'T' के आकार पर रखा जाता है) इसके tee() तरीके का इस्तेमाल किया जा सकता है. इससे स्ट्रीम लॉक हो जाएगी. इसका मतलब है कि स्ट्रीम को सीधे तौर पर इस्तेमाल नहीं किया जा सकेगा; हालांकि, यह दो नए स्ट्रीम, जिन्हें ब्रांच कहा जाता है, जिन्हें अलग-अलग इस्तेमाल किया जा सकता है. टीयर करना इसलिए भी ज़रूरी है, क्योंकि स्ट्रीम को न तो फिर से चालू किया जा सकता है और न ही रीस्टार्ट किया जा सकता है. इसके बारे में ज़्यादा जानकारी बाद में दी जाएगी.

पाइप चेन का डायग्राम, जिसमें फ़ेच एपीआई को कॉल करने से आने वाली ऐसी स्ट्रीम शामिल है जिसे पढ़ा जा सकता है. इसके बाद, इसे ट्रांसफ़ॉर्म स्ट्रीम से पाइप किया जाता है, जिसका आउटपुट टेस्ट किया जाता है. इसके बाद, पढ़ने लायक पहली स्ट्रीम के लिए ब्राउज़र को भेजा जाता है. साथ ही, दूसरी पढ़ने लायक स्ट्रीम के लिए सर्विस वर्कर कैश को भेजा जाता है.
पाइप चेन.

आसानी से पढ़ी जा सकने वाली स्ट्रीम की तकनीक

पढ़ने लायक स्ट्रीम एक डेटा सोर्स होती है. इसे JavaScript में ReadableStream ऑब्जेक्ट जो पहले से मौजूद सोर्स से फ़्लो करता है. कॉन्टेंट बनाने ReadableStream() कंस्ट्रक्टर एक ऐसा स्ट्रीम ऑब्जेक्ट बनाता है जो दिए गए हैंडलर से आसानी से पढ़ा जा सकता है. दो दिए गए सोर्स के टाइप:

  • पुश सोर्स की मदद से, डेटा को लगातार ऐक्सेस किया जाता है. ऐसा तब किया जाता है, जब आपने उसे ऐक्सेस किया हो स्ट्रीम का ऐक्सेस चालू करें, रोकें या उसे रद्द करें. उदाहरण के लिए, लाइव वीडियो स्ट्रीम, सर्वर से भेजे गए इवेंट, या WebSockets.
  • पुल सोर्स को कनेक्ट करने के बाद, आपको उनसे डेटा का अनुरोध साफ़ तौर पर करना होगा. उदाहरण fetch() या XMLHttpRequest कॉल के ज़रिए एचटीटीपी कार्रवाइयां शामिल करें.

स्ट्रीम के डेटा को एक के बाद एक छोटे-छोटे हिस्सों में पढ़ा जाता है. इन हिस्सों को ग्रुप कहा जाता है. किसी स्ट्रीम में रखे गए हिस्से के लिए, एक साथ सूची में कहा जाता है. इसका मतलब है कि वे कतार में इंतज़ार कर रहे हैं पढ़े जाने के लिए तैयार रहता है. इंटरनल लिस्ट, उन हिस्सों का ट्रैक रखती है जिन्हें अब तक पढ़ा नहीं गया है.

सूची बनाने की रणनीति एक ऐसा ऑब्जेक्ट है जो तय करता है कि किसी स्ट्रीम को इसकी अंदरूनी सूची की स्थिति क्या है. कतार में शामिल करने की रणनीति, हर हिस्से के लिए एक आकार तय करती है और किसी तय संख्या के लिए, सूची में सभी हिस्से का कुल साइज़. इसे हाई वॉटर मार्क कहा जाता है.

स्ट्रीम के अंदर के हिस्सों को रीडर पढ़ सकता है. यह रीडर, पूरे डेटा को हर बार समय की मदद से, आप इस पर जो भी काम करना चाहते हैं वह किया जा सकता है. पाठक और अन्य इसके साथ चलने वाले प्रोसेसिंग कोड को उपभोक्ता कहा जाता है.

इस संदर्भ में अगले निर्माण को कंट्रोलर कहा जाता है. आसानी से पढ़ी जा सकने वाली हर स्ट्रीम के साथ कंट्रोलर की मदद से स्ट्रीम को कंट्रोल किया जा सकता है.

एक बार में सिर्फ़ एक व्यक्ति किसी स्ट्रीम को पढ़ सकता है; जब कोई रीडर बनाया जाता है और स्ट्रीम को पढ़ना शुरू करता है (जो एक ऐक्टिव रीडर बन जाता है), उससे लॉक हो जाता है. अगर आपको किसी दूसरे पाठक को पढ़े जाने पर, आम तौर पर कुछ भी करने से पहले आपको पहले रीडर को रिलीज़ करना होगा हालांकि, टी लाइव स्ट्रीम की जा सकती है.

ऐसी स्ट्रीम बनाना जिसे आसानी से पढ़ा जा सके

इसके कंस्ट्रक्टर को कॉल करके, कोई ऐसी स्ट्रीम बनाएं जिसे आसानी से पढ़ा जा सके ReadableStream(). कंस्ट्रक्टर में एक वैकल्पिक आर्ग्युमेंट underlyingSource है, जो किसी ऑब्जेक्ट के बारे में बताता है उन तरीकों और प्रॉपर्टी से तय करें जो तय करते हैं कि बनाया गया स्ट्रीम इंस्टेंस कैसे काम करेगा.

underlyingSource

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

  • start(controller): ऑब्जेक्ट बन जाते ही तुरंत कॉल किया जाता है. कॉन्टेंट बनाने वाला तरीका, स्ट्रीम के सोर्स को ऐक्सेस कर सकता है. इसके अलावा, स्ट्रीम फ़ंक्शन सेट अप करने के लिए ज़रूरी है. अगर इस प्रोसेस को एसिंक्रोनस रूप से किया जाना है, तो यह तरीका सफलता या असफलता के बारे में बताने का वादा करना. इस तरीके को पास किया गया controller पैरामीटर है एक ReadableStreamDefaultController.
  • pull(controller): स्ट्रीम को कंट्रोल करने के लिए इसका इस्तेमाल किया जा सकता है, क्योंकि ज़्यादा हिस्से फ़ेच किए जाते हैं. यह को बार-बार कॉल किया जाता है, जब तक कि स्ट्रीम में मौजूद हिस्सों की सूची पूरी न हो, तब तक की सूची चालू न हो अपने उच्च जल चिह्न तक पहुँच जाता है. अगर pull() को कॉल करने का फ़ैसला सही है, तो जब तक यह वादा पूरा नहीं होता, तब तक pull() को दोबारा कॉल नहीं किया जाएगा. अगर प्रॉमिस अस्वीकार कर दिया जाता है, तो स्ट्रीम में गड़बड़ी हो जाएगी.
  • cancel(reason): इसे तब कॉल किया जाता है, जब स्ट्रीम करने वाला व्यक्ति स्ट्रीम को रद्द कर देता है.
const readableStream = new ReadableStream({
  start(controller) {
    /* … */
  },

  pull(controller) {
    /* … */
  },

  cancel(reason) {
    /* … */
  },
});

ReadableStreamDefaultController में ये तरीके काम करते हैं:

  • ReadableStreamDefaultController.close() इससे जुड़ी स्ट्रीम को बंद कर देता है.
  • ReadableStreamDefaultController.enqueue() इससे जुड़ी स्ट्रीम में दिए गए हिस्से को क्यू में लगाता है.
  • ReadableStreamDefaultController.error() की वजह से, आने वाले समय में इससे जुड़ी स्ट्रीम के साथ होने वाले इंटरैक्शन में गड़बड़ी हो सकती है.
/* … */
start(controller) {
  controller.enqueue('The first chunk!');
},
/* … */

queuingStrategy

दूसरा, ReadableStream() कंस्ट्रक्टर का आर्ग्युमेंट, queuingStrategy है. हालांकि, ऐसा करना ज़रूरी नहीं है. यह एक ऑब्जेक्ट है, जो वैकल्पिक रूप से स्ट्रीम के लिए सूची बनाने की रणनीति तय करता है, जिसमें दो पैरामीटर:

  • highWaterMark: कतार में शामिल करने की इस रणनीति का इस्तेमाल करके, धारा के उच्च जल चिह्न को दिखाने वाली एक गैर-ऋणात्मक संख्या.
  • size(chunk): ऐसा फ़ंक्शन जो दिए गए समूह की वैल्यू के सीमित गैर-ऋणात्मक आकार की गणना करता है और उसे नतीजे के तौर पर दिखाता है. इस नतीजे का इस्तेमाल, बैक प्रेशर तय करने के लिए किया जाता है. साथ ही, इसे सही ReadableStreamDefaultController.desiredSize प्रॉपर्टी के ज़रिए दिखाया जाता है. यह तब भी लागू होता है, जब सोर्स के pull() तरीके को कॉल किया जाता है.
const readableStream = new ReadableStream({
    /* … */
  },
  {
    highWaterMark: 10,
    size(chunk) {
      return chunk.length;
    },
  },
);

getReader() और read() तरीके

किसी पढ़ने लायक स्ट्रीम से पढ़ने के लिए, आपको एक रीडर की ज़रूरत होगी. यह ReadableStreamDefaultReader. ReadableStream इंटरफ़ेस का getReader() तरीका, एक रीडर बनाता है और स्ट्रीम को इस पर लॉक करता है: इसे. स्ट्रीम के लॉक होने पर, इस स्ट्रीम को रिलीज़ करने से पहले, किसी और पाठक के साथ इसका इस्तेमाल नहीं किया जा सकता.

read() ReadableStreamDefaultReader इंटरफ़ेस की विधि अगले स्ट्रीम की अंदरूनी सूची में डेटा का एक हिस्सा शामिल करें. यह नतीजे के साथ पूरा या अस्वीकार करता है. यह इस बात पर निर्भर करता है कि स्ट्रीम. अलग-अलग संभावनाएं इस तरह हैं:

  • अगर प्रॉडक्ट का कोई हिस्सा उपलब्ध है, तो इस फ़ॉर्म के ऑब्जेक्ट के साथ प्रॉमिस को पूरा किया जाएगा
    { value: chunk, done: false }.
  • अगर स्ट्रीम बंद हो जाती है, तो प्रॉमिस फ़ॉर्म के ऑब्जेक्ट के साथ पूरा होगा
    { value: undefined, done: true }.
  • अगर स्ट्रीम में कोई गड़बड़ी होती है, तो सही गड़बड़ी के साथ प्रॉमिस अस्वीकार कर दिया जाएगा.
const reader = readableStream.getReader();
while (true) {
  const { done, value } = await reader.read();
  if (done) {
    console.log('The stream is done.');
    break;
  }
  console.log('Just read a chunk:', value);
}

locked प्रॉपर्टी

अगर आसानी से पढ़ा जा सकने वाली स्ट्रीम लॉक है, तो ReadableStream.locked प्रॉपर्टी.

const locked = readableStream.locked;
console.log(`The stream is ${locked ? 'indeed' : 'not'} locked.`);

पढ़ने लायक स्ट्रीम कोड के नमूने

नीचे दिया गया कोड सैंपल, सभी चरणों को दिखाता है. आप सबसे पहले एक ReadableStream बनाते हैं, जो underlyingSource आर्ग्युमेंट (यानी कि TimestampSource क्लास), start() तरीके को तय करता है. यह तरीका, स्ट्रीम के controller को दस सेकंड के दौरान हर सेकंड एक टाइमस्टैंप enqueue() करें. आखिर में, यह कंट्रोलर को स्ट्रीम को close() करने के लिए कहता है. आप इसका इस्तेमाल करते हैं स्ट्रीम करने के लिए, getReader() तरीके से रीडर बनाएं और read() को कॉल करें. ऐसा तब तक होगा, जब तक स्ट्रीम done.

class TimestampSource {
  #interval

  start(controller) {
    this.#interval = setInterval(() => {
      const string = new Date().toLocaleTimeString();
      // Add the string to the stream.
      controller.enqueue(string);
      console.log(`Enqueued ${string}`);
    }, 1_000);

    setTimeout(() => {
      clearInterval(this.#interval);
      // Close the stream after 10s.
      controller.close();
    }, 10_000);
  }

  cancel() {
    // This is called if the reader cancels.
    clearInterval(this.#interval);
  }
}

const stream = new ReadableStream(new TimestampSource());

async function concatStringStream(stream) {
  let result = '';
  const reader = stream.getReader();
  while (true) {
    // The `read()` method returns a promise that
    // resolves when a value has been received.
    const { done, value } = await reader.read();
    // Result objects contain two properties:
    // `done`  - `true` if the stream has already given you all its data.
    // `value` - Some data. Always `undefined` when `done` is `true`.
    if (done) return result;
    result += value;
    console.log(`Read ${result.length} characters so far`);
    console.log(`Most recently read chunk: ${value}`);
  }
}
concatStringStream(stream).then((result) => console.log('Stream complete', result));

एसिंक्रोनस इटरेशन

अगर स्ट्रीम done है, तो हर read() लूप इटरेशन की जांच की जा रही है. ऐसा हो सकता है कि यह सबसे सुविधाजनक एपीआई न हो. अच्छी बात यह है कि ऐसा करने का बेहतर तरीका जल्द ही उपलब्ध होगा: एसिंक्रोनस इटरेशन.

for await (const chunk of stream) {
  console.log(chunk);
}
अभी तक किसी भी व्यक्ति ने चेक इन नहीं किया है

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

if (!ReadableStream.prototype[Symbol.asyncIterator]) {
  ReadableStream.prototype[Symbol.asyncIterator] = async function* () {
    const reader = this.getReader();
    try {
      while (true) {
        const {done, value} = await reader.read();
        if (done) {
          return;
          }
        yield value;
      }
    }
    finally {
      reader.releaseLock();
    }
  }
}

आसानी से पढ़ा जा सकने वाली स्ट्रीम जोड़ना

tee() तरीका ReadableStream इंटरफ़ेस की मदद से, पढ़ी जा सकने वाली मौजूदा स्ट्रीम को शामिल किया जाता है. इससे, दो एलिमेंट वाला अरे दिखता है इसमें दो ब्रांचों को नए ReadableStream इंस्टेंस के तौर पर शामिल किया गया है. इससे आपको जिसमें दो लोग एक साथ स्ट्रीम पढ़ सकते हैं. उदाहरण के लिए, सर्विस वर्कर में आप ऐसा तब कर सकते हैं, जब की मदद से, सर्वर से मिले रिस्पॉन्स को ब्राउज़र पर स्ट्रीम किया जा सकता है. साथ ही, सर्विस वर्कर कैश मेमोरी में सेव किया गया. जवाब के मुख्य हिस्से को एक से ज़्यादा बार इस्तेमाल नहीं किया जा सकता. इसलिए, आपको इसकी दो कॉपी अपलोड करनी होंगी आपको ऐसा करना होगा. स्ट्रीम को रद्द करने के लिए, आपको इसकी दोनों ब्रांच रद्द करनी होंगी. संगीत का आनंद लें आम तौर पर इसे उतने समय के लिए लॉक कर देगा, ताकि अन्य लोग उसे लॉक न कर सकें.

const readableStream = new ReadableStream({
  start(controller) {
    // Called by constructor.
    console.log('[start]');
    controller.enqueue('a');
    controller.enqueue('b');
    controller.enqueue('c');
  },
  pull(controller) {
    // Called `read()` when the controller's queue is empty.
    console.log('[pull]');
    controller.enqueue('d');
    controller.close();
  },
  cancel(reason) {
    // Called when the stream is canceled.
    console.log('[cancel]', reason);
  },
});

// Create two `ReadableStream`s.
const [streamA, streamB] = readableStream.tee();

// Read streamA iteratively one by one. Typically, you
// would not do it this way, but you certainly can.
const readerA = streamA.getReader();
console.log('[A]', await readerA.read()); //=> {value: "a", done: false}
console.log('[A]', await readerA.read()); //=> {value: "b", done: false}
console.log('[A]', await readerA.read()); //=> {value: "c", done: false}
console.log('[A]', await readerA.read()); //=> {value: "d", done: false}
console.log('[A]', await readerA.read()); //=> {value: undefined, done: true}

// Read streamB in a loop. This is the more common way
// to read data from the stream.
const readerB = streamB.getReader();
while (true) {
  const result = await readerB.read();
  if (result.done) break;
  console.log('[B]', result);
}

पढ़ने लायक बाइट स्ट्रीम

बाइट दिखाने वाली स्ट्रीम के लिए, पढ़ने लायक स्ट्रीम का बड़ा वर्शन दिया गया है, ताकि खास तौर पर, कॉपी को छोटा करके. बाइट स्ट्रीम की मदद से, बफ़र का इस्तेमाल अपने हिसाब से किया जा सकता है (BYOB) वाले पाठकों को हासिल करना. डिफ़ॉल्ट रूप से लागू होने पर कई तरह के आउटपुट मिल सकते हैं, जैसे कि WebSockets के मामले में स्ट्रिंग या अरे बफ़र का इस्तेमाल किया जाता है, जबकि बाइट स्ट्रीम, बाइट आउटपुट की गारंटी देती हैं. इसके अलावा, बीवायओबी (BYOB) वाले पाठकों को स्थिरता से जुड़े फ़ायदे मिलते हैं. यह है क्योंकि अगर कोई बफ़र अलग होता है, तो यह गारंटी दे सकता है कि कोई एक ही बफ़र में दो बार नहीं लिखता, इसलिए रेस की स्थितियों से बचें. BYOB रीडर, ब्राउज़र को चलाने की ज़रूरत को कम कर सकता है गार्बेज कलेक्शन को ऐक्सेस किया जा सकता है, क्योंकि यह बफ़र का फिर से इस्तेमाल कर सकता है.

पढ़ने लायक बाइट स्ट्रीम बनाना

आपtype ReadableStream() कंस्ट्रक्टर.

new ReadableStream({ type: 'bytes' });

underlyingSource

पढ़ने लायक बाइट स्ट्रीम के बुनियादी सोर्स को, ReadableByteStreamController हेर-फेर करना. इसकी ReadableByteStreamController.enqueue() विधि में एक chunk तर्क होता है जिसका मान एक ArrayBufferView है. प्रॉपर्टी ReadableByteStreamController.byobRequest मौजूदा वैल्यू दिखाता है BYOB पुल का अनुरोध या अगर कोई अनुरोध नहीं है, तो यह शून्य है. आखिर में, ReadableByteStreamController.desiredSize प्रॉपर्टी, कंट्रोल वाली स्ट्रीम की इंटरनल लिस्ट को भरने के लिए मनचाहे साइज़ का इस्तेमाल करती है.

queuingStrategy

दूसरा, ReadableStream() कंस्ट्रक्टर का आर्ग्युमेंट, queuingStrategy है. हालांकि, ऐसा करना ज़रूरी नहीं है. यह एक ऑब्जेक्ट है, जो वैकल्पिक रूप से स्ट्रीम के लिए सूची बनाने की रणनीति तय करता है, जो पैरामीटर:

  • highWaterMark: कतार में शामिल करने की इस रणनीति का इस्तेमाल करके, स्ट्रीम के हाई वॉटर निशान को दिखाने वाली बाइट की नॉन-नेगेटिव संख्या. इसका इस्तेमाल, बैक प्रेशर तय करने के लिए किया जाता है. साथ ही, इसे सही ReadableByteStreamController.desiredSize प्रॉपर्टी के ज़रिए दिखाया जाता है. यह तब भी लागू होता है, जब सोर्स के pull() तरीके को कॉल किया जाता है.

getReader() और read() तरीके

इसके बाद, mode पैरामीटर को उसी हिसाब से सेट करके, ReadableStreamBYOBReader का ऐक्सेस पाएं: ReadableStream.getReader({ mode: "byob" }). इससे बफ़र को बेहतर तरीके से कंट्रोल किया जा सकता है कॉपी न करने के लिए किया जा सकता है. बाइट स्ट्रीम से पढ़ने के लिए, आपको कॉल करना होगा ReadableStreamBYOBReader.read(view), जहां view ArrayBufferView.

पढ़ने लायक बाइट के स्ट्रीम कोड का सैंपल

const reader = readableStream.getReader({ mode: "byob" });

let startingAB = new ArrayBuffer(1_024);
const buffer = await readInto(startingAB);
console.log("The first 1024 bytes, or less:", buffer);

async function readInto(buffer) {
  let offset = 0;

  while (offset < buffer.byteLength) {
    const { value: view, done } =
        await reader.read(new Uint8Array(buffer, offset, buffer.byteLength - offset));
    buffer = view.buffer;
    if (done) {
      break;
    }
    offset += view.byteLength;
  }

  return buffer;
}

नीचे दिया गया फ़ंक्शन, पढ़ने लायक बाइट स्ट्रीम दिखाता है, जो रैंडम तरीके से जनरेट किया गया कलेक्शन. पहले से तय किए गए 1,024 वाले डेटा ग्रुप के बजाय, यह डेवलपर से मिला बफ़र, पूरे कंट्रोल की अनुमति देता है.

const DEFAULT_CHUNK_SIZE = 1_024;

function makeReadableByteStream() {
  return new ReadableStream({
    type: 'bytes',

    pull(controller) {
      // Even when the consumer is using the default reader,
      // the auto-allocation feature allocates a buffer and
      // passes it to us via `byobRequest`.
      const view = controller.byobRequest.view;
      view = crypto.getRandomValues(view);
      controller.byobRequest.respond(view.byteLength);
    },

    autoAllocateChunkSize: DEFAULT_CHUNK_SIZE,
  });
}

लिखने की स्ट्रीम की तकनीक

लिखने लायक स्ट्रीम वह डेस्टिनेशन है जिसमें डेटा लिखा जा सकता है. इसे JavaScript में WritableStream ऑब्जेक्ट. यह अंडरग्राउंड सिंक के ऊपरी हिस्से पर एक ऐब्स्ट्रैक्ट का काम करता है—निचले-लेवल के I/O सिंक में रॉ डेटा को लिखा जाता है.

डेटा को स्ट्रीम में लेखक की मदद से लिखा जाता है. एक बार में एक डेटा का इस्तेमाल किया जाता है. कई लोग में मौजूद अलग-अलग तरह के कई रूपों को हूबहू दिखाना. आप जो भी कोड बनाना चाहते हैं उसका इस्तेमाल कर सकते हैं लिखने के लिए तैयार हिस्से; राइटर और उससे जुड़े कोड को प्रोड्यूसर कहा जाता है.

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

इंटरनल सूची से, स्ट्रीम में शामिल उन हिस्सों का ट्रैक रखा जाता है जिन्हें अब तक स्ट्रीम में नहीं लिखा गया है सिंक से प्रोसेस किया जाता है.

सूची बनाने की रणनीति एक ऐसा ऑब्जेक्ट है जो तय करता है कि किसी स्ट्रीम को इसकी अंदरूनी सूची की स्थिति क्या है. कतार में शामिल करने की रणनीति, हर हिस्से के लिए एक आकार तय करती है और किसी तय संख्या के लिए, सूची में सभी हिस्से का कुल साइज़. इसे हाई वॉटर मार्क कहा जाता है.

आखिरी निर्माण को कंट्रोलर कहा जाता है. लिखने वाली हर स्ट्रीम से जुड़ा एक कंट्रोलर होता है, जो आपको स्ट्रीम को कंट्रोल करने की अनुमति देता है. उदाहरण के लिए, उसे रद्द करने के लिए.

ऐसी स्ट्रीम बनाना जिस पर कुछ लिखा जा सके

इसका WritableStream इंटरफ़ेस Streams API, किसी डेस्टिनेशन पर स्ट्रीमिंग डेटा लिखने के लिए एक स्टैंडर्ड ऐब्स्ट्रक्शन उपलब्ध कराता है. सिंक की तरह है. इस ऑब्जेक्ट में पहले से मौजूद बैक प्रेशर और लाइन की सुविधा मौजूद है. आप इसके ज़रिए एक लिखने योग्य स्ट्रीम बनाते हैं इसके कंस्ट्रक्टर को कॉल करना WritableStream(). इसमें एक वैकल्पिक underlyingSink पैरामीटर है, जो किसी ऑब्जेक्ट के बारे में बताता है उन तरीकों और प्रॉपर्टी से तय करें जो तय करते हैं कि बनाया गया स्ट्रीम इंस्टेंस कैसे काम करेगा.

underlyingSink

underlyingSink में, डेवलपर के तय किए गए इन वैकल्पिक तरीकों को शामिल किया जा सकता है. controller कुछ तरीकों को पास किया जाने वाला पैरामीटर WritableStreamDefaultController.

  • start(controller): ऑब्जेक्ट बन जाने के बाद, यह तरीका तुरंत कॉल कर दिया जाता है. कॉन्टेंट बनाने इस तरीके के कॉन्टेंट का मकसद, सिंक की सुविधा को ऐक्सेस करना होना चाहिए. अगर इस प्रक्रिया को किया जाता है, तो यह सफलता या विफलता के सिग्नल का प्रॉमिस दे सकता है.
  • write(chunk, controller): यह तरीका तब कॉल किया जाएगा, जब डेटा का नया हिस्सा (यह डेटा chunk पैरामीटर) अब सिंक में लिखे जाने के लिए तैयार है. यह सिग्नल सही से काम नहीं कर रहा या काम नहीं कर रहा. यह तरीका पिछले चरण के बाद ही कॉल किया जाएगा लिखना सफल रहा और स्ट्रीम बंद या रद्द होने के बाद कभी नहीं.
  • close(controller): अगर ऐप्लिकेशन को लगता है कि इसने पूरा टेक्स्ट लिख लिया है, तो इस तरीके को कॉल किया जाएगा हिस्से में बांटता है. कॉन्टेंट को पूरी कोशिश करनी चाहिए कि सिंक कर देता है और उसे ऐक्सेस कर देता है. अगर यह प्रक्रिया एसिंक्रोनस है, तो यह सफलता या असफलता के बारे में बताने का वादा करना. यह तरीका सिर्फ़ तब कॉल किया जाएगा, जब सभी लोग सूची में शामिल हो जाएंगे. सफल हुए.
  • abort(reason): अगर ऐप्लिकेशन को अचानक बंद होने का मैसेज मिलता है, तो इस तरीके को कॉल किया जाएगा और उसे एक गड़बड़ी की स्थिति में डाल दिया जाए. यह किसी भी मौजूदा संसाधन को साफ़ कर सकता है, जैसे कि close(), लेकिन abort() को कॉल किया जाएगा, भले ही पंक्तियों को सूची में रखा गया हो. ये हिस्से फेंक दिए जाएंगे दूर. अगर यह प्रोसेस एसिंक्रोनस है, तो हो सकता है कि इससे रिस्पॉन्स मिलने या न होने का सिग्नल मिल जाए. कॉन्टेंट बनाने reason पैरामीटर में एक DOMString शामिल है, जिसमें बताया गया है कि स्ट्रीम को क्यों रोका गया था.
const writableStream = new WritableStream({
  start(controller) {
    /* … */
  },

  write(chunk, controller) {
    /* … */
  },

  close(controller) {
    /* … */
  },

  abort(reason) {
    /* … */
  },
});

कॉन्टेंट बनाने WritableStreamDefaultController Streams API का इंटरफ़ेस, एक ऐसा कंट्रोलर दिखाता है जो WritableStream की स्थिति को कंट्रोल करने की अनुमति देता है सेट अप के दौरान, लिखने के लिए या लिखने के आखिर में ज़्यादा हिस्से सबमिट किए जाते हैं. निर्माण करते समय एक WritableStream है, तो सिंक की वैल्यू को उससे जुड़ा WritableStreamDefaultController दिया जाता है इस्तेमाल नहीं किया जा सकता. WritableStreamDefaultController में सिर्फ़ एक तरीका होता है: WritableStreamDefaultController.error(), इसकी वजह से, आने वाले समय में, स्ट्रीम से जुड़ी किसी भी बातचीत में गड़बड़ी हो सकती है. WritableStreamDefaultController ऐसी signal प्रॉपर्टी के साथ भी काम करता है जो AbortSignal, इससे, ज़रूरत पड़ने पर WritableStream की कार्रवाई को रोका जा सकता है.

/* … */
write(chunk, controller) {
  try {
    // Try to do something dangerous with `chunk`.
  } catch (error) {
    controller.error(error.message);
  }
},
/* … */

queuingStrategy

दूसरा, WritableStream() कंस्ट्रक्टर का आर्ग्युमेंट, queuingStrategy है. हालांकि, ऐसा करना ज़रूरी नहीं है. यह एक ऑब्जेक्ट है, जो वैकल्पिक रूप से स्ट्रीम के लिए सूची बनाने की रणनीति तय करता है, जिसमें दो पैरामीटर:

  • highWaterMark: कतार में शामिल करने की इस रणनीति का इस्तेमाल करके, धारा के उच्च जल चिह्न को दिखाने वाली एक गैर-ऋणात्मक संख्या.
  • size(chunk): ऐसा फ़ंक्शन जो दिए गए समूह की वैल्यू के सीमित गैर-ऋणात्मक आकार की गणना करता है और उसे नतीजे के तौर पर दिखाता है. इस नतीजे का इस्तेमाल, बैक प्रेशर तय करने के लिए किया जाता है. साथ ही, इसे सही WritableStreamDefaultWriter.desiredSize प्रॉपर्टी के ज़रिए दिखाया जाता है.

getWriter() और write() तरीके

एक लिखने योग्य स्ट्रीम में लिखने के लिए, आपको एक लेखक की ज़रूरत होगी, जो WritableStreamDefaultWriter. WritableStream इंटरफ़ेस की getWriter() तरीका, WritableStreamDefaultWriter का नया इंस्टेंस जनरेट करता है और स्ट्रीम को उस इंस्टेंस पर लॉक करता है. हालांकि स्ट्रीम को लॉक किया गया है. जब तक मौजूदा राइटर रिलीज़ नहीं हो जाता, तब तक कोई अन्य लेखक नहीं चुना जा सकता.

write() का तरीका WritableStreamDefaultWriter इंटरफ़ेस, WritableStream और उसके मौजूदा सिंक में, पास किए गए डेटा का कुछ हिस्सा लिखता है और फिर वापस लौटाता है एक ऐसा प्रॉमिस जो राइट ऑपरेशन की सफलता या असफलता को दिखाता है. ध्यान दें कि "सफलता" का मतलब, सिंक की प्रोसेस से तय होता है; इससे यह पता चल सकता है कि डेटा समूह को स्वीकार कर लिया गया है, और ऐसा ज़रूरी नहीं है कि उसे सुरक्षित तरीके से अपनी मंज़िल पर सेव कर लिया जाए.

const writer = writableStream.getWriter();
const resultPromise = writer.write('The first chunk!');

locked प्रॉपर्टी

आप देख सकते हैं कि लिखने योग्य स्ट्रीम लॉक है या नहीं. WritableStream.locked प्रॉपर्टी.

const locked = writableStream.locked;
console.log(`The stream is ${locked ? 'indeed' : 'not'} locked.`);

राइट किए जा सकने वाले स्ट्रीम कोड का सैंपल

नीचे दिया गया कोड सैंपल, सभी चरणों को दिखाता है.

const writableStream = new WritableStream({
  start(controller) {
    console.log('[start]');
  },
  async write(chunk, controller) {
    console.log('[write]', chunk);
    // Wait for next write.
    await new Promise((resolve) => setTimeout(() => {
      document.body.textContent += chunk;
      resolve();
    }, 1_000));
  },
  close(controller) {
    console.log('[close]');
  },
  abort(reason) {
    console.log('[abort]', reason);
  },
});

const writer = writableStream.getWriter();
const start = Date.now();
for (const char of 'abcdefghijklmnopqrstuvwxyz') {
  // Wait to add to the write queue.
  await writer.ready;
  console.log('[ready]', Date.now() - start, 'ms');
  // The Promise is resolved after the write finishes.
  writer.write(char);
}
await writer.close();

पढ़ने लायक स्ट्रीम को राइट की जा सकने वाली स्ट्रीम में जोड़ना

किसी पढ़ने लायक स्ट्रीम को पढ़ने लायक स्ट्रीम के pipeTo() तरीका. ReadableStream.pipeTo(), मौजूदा ReadableStream को दिए गए WritableStream से पाइप करता है और ऐसा वादा जो पाइपिंग की प्रोसेस के पूरा होने पर पूरा होता हो. इसके अलावा, अगर कोई गड़बड़ी होती है, तो वह उसे अस्वीकार कर देता है मिला.

const readableStream = new ReadableStream({
  start(controller) {
    // Called by constructor.
    console.log('[start readable]');
    controller.enqueue('a');
    controller.enqueue('b');
    controller.enqueue('c');
  },
  pull(controller) {
    // Called when controller's queue is empty.
    console.log('[pull]');
    controller.enqueue('d');
    controller.close();
  },
  cancel(reason) {
    // Called when the stream is canceled.
    console.log('[cancel]', reason);
  },
});

const writableStream = new WritableStream({
  start(controller) {
    // Called by constructor
    console.log('[start writable]');
  },
  async write(chunk, controller) {
    // Called upon writer.write()
    console.log('[write]', chunk);
    // Wait for next write.
    await new Promise((resolve) => setTimeout(() => {
      document.body.textContent += chunk;
      resolve();
    }, 1_000));
  },
  close(controller) {
    console.log('[close]');
  },
  abort(reason) {
    console.log('[abort]', reason);
  },
});

await readableStream.pipeTo(writableStream);
console.log('[finished]');

पूरी तरह बदलने वाली स्ट्रीम बनाना

Streams API का TransformStream इंटरफ़ेस, ऐसे डेटा का सेट दिखाता है जिसमें बदलाव किया जा सकता है. आपने लोगों तक पहुंचाया मुफ़्त में इसके कंस्ट्रक्टर TransformStream() को कॉल करके एक ट्रांसफ़ॉर्म स्ट्रीम बनाएं. यह स्ट्रीम बनाता है और दिखाता है दिए गए हैंडलर से एक ट्रांसफ़ॉर्म स्ट्रीम ऑब्जेक्ट. TransformStream() कंस्ट्रक्टर पहला आर्ग्युमेंट, transformer के बारे में बताने वाला एक वैकल्पिक JavaScript ऑब्जेक्ट है. ऐसी चीज़ें ये काम कर सकती हैं: इनमें से कोई भी तरीका इस्तेमाल करें:

transformer

  • start(controller): ऑब्जेक्ट बन जाने के बाद, यह तरीका तुरंत कॉल कर दिया जाता है. आम तौर पर इसका इस्तेमाल, controller.enqueue() का इस्तेमाल करके, प्रीफ़िक्स चंक को एनक्यू में करने के लिए किया जाता है. इन हिस्सों को पढ़ा जाएगा लिखने के लिए इस्तेमाल किया जाता है. हालांकि, लिखने के लिए किसी भी तरफ़ लिखने पर निर्भर नहीं रहना पड़ता. अगर इस नाम की शुरुआत में प्रक्रिया एसिंक्रोनस होती है. उदाहरण के लिए, क्योंकि प्रीफ़िक्स के हिस्से हासिल करने में थोड़ी मेहनत लगती है, फ़ंक्शन सही या फ़ेल होने का सिग्नल देने का प्रॉमिस लौटा सकता हो; वादे को अस्वीकार करने पर गड़बड़ी का मैसेज स्ट्रीम. थ्रॉ किए गए किसी भी अपवाद को TransformStream() कंस्ट्रक्टर फिर से थ्रो कर देगा.
  • transform(chunk, controller): यह तरीका तब कहा जाता है, जब मूल रूप से लिखने वाला हिस्सा बदलने के लिए तैयार है. स्ट्रीम लागू करने से यह गारंटी मिलती है कि यह फ़ंक्शन पिछले बदलावों के पूरा होने के बाद ही कॉल किया जाएगा और start() से पहले कभी नहीं हुआ पूरा हो गया है या flush() पर कॉल किए जाने के बाद. यह फ़ंक्शन असल बदलाव करता है ट्रांसफ़ॉर्म स्ट्रीम का काम कर रहे थे. यह controller.enqueue() का इस्तेमाल करके, नतीजों को सूची में जोड़ सकती है. यह लिखने लायक एक तरफ़ के एक हिस्से को लिखने की अनुमति देता है, जिससे उस हिस्से में शून्य या एक से ज़्यादा हिस्से आते हैं controller.enqueue() को कितनी बार कॉल किया गया है, इसके आधार पर पढ़ने में आसान. अगर प्रोसेस को ट्रांसफ़ॉर्मिंग एसिंक्रोनस है. इसलिए, यह फ़ंक्शन इस तरह की क्वेरी के जवाब में सफलता या असफलता का प्रॉमिस दे सकता है बदलाव लाने के लिए इस्तेमाल किया जा सकता है. अस्वीकार किए गए प्रॉमिस की वजह से पूरी तरह बदलो. अगर कोई transform() तरीका नहीं दिया जाता है, तो आइडेंटिटी ट्रांसफ़ॉर्म का इस्तेमाल किया जाता है, जिसमें कतार में मौजूद डेटा के हिस्से, पढ़े जा सकने वाले हिस्से में नहीं दिखेंगे.
  • flush(controller): इस तरीके को तब कॉल किया जाता है, जब लिखने लायक हिस्से में सभी हिस्से transform() से होकर गुज़रकर पूरी तरह बदली गई और लिखने लायक हिस्सा करीब-करीब बंद. आम तौर पर, इसका इस्तेमाल आसानी से पढ़े जा सकने वाले हिस्से में सफ़िक्स को क्यू में लगाने के लिए किया जाता है. इसके पहले भी ऐसा किया जाता है बंद हो जाता है. अगर सफ़ाई की प्रोसेस एसिंक्रोनस है, तो फ़ंक्शन सिग्नल मिल रहा है या नहीं हो सकता; इसके नतीजे की जानकारी इसके कॉलर को दी जाएगी stream.writable.write(). इसके अलावा, अस्वीकार किए गए प्रॉमिस में, पढ़ने में आसान और लिखना आसान हो जाएगा. किसी अपवाद को फेंकने पर, अस्वीकार किया गया जवाब देने जैसा ही माना जाता है वादा करना.
const transformStream = new TransformStream({
  start(controller) {
    /* … */
  },

  transform(chunk, controller) {
    /* … */
  },

  flush(controller) {
    /* … */
  },
});

सूची में शामिल करने के लिए, writableStrategy और readableStrategy रणनीतियां

TransformStream() कंस्ट्रक्टर के दूसरे और तीसरे वैकल्पिक पैरामीटर ज़रूरी नहीं हैं सूची में शामिल करने के लिए, writableStrategy और readableStrategy रणनीतियां. इनकी परिभाषा पढ़ने लायक और लिखने लायक स्ट्रीम सेक्शन भी मिलते हैं.

स्ट्रीम कोड का सैंपल बदलें

नीचे दिया गया कोड सैंपल, स्ट्रीम को आसानी से बदलने का तरीका दिखाता है.

// Note that `TextEncoderStream` and `TextDecoderStream` exist now.
// This example shows how you would have done it before.
const textEncoderStream = new TransformStream({
  transform(chunk, controller) {
    console.log('[transform]', chunk);
    controller.enqueue(new TextEncoder().encode(chunk));
  },
  flush(controller) {
    console.log('[flush]');
    controller.terminate();
  },
});

(async () => {
  const readStream = textEncoderStream.readable;
  const writeStream = textEncoderStream.writable;

  const writer = writeStream.getWriter();
  for (const char of 'abc') {
    writer.write(char);
  }
  writer.close();

  const reader = readStream.getReader();
  for (let result = await reader.read(); !result.done; result = await reader.read()) {
    console.log('[value]', result.value);
  }
})();

ट्रांसफ़ॉर्म स्ट्रीम के ज़रिए पढ़ने लायक स्ट्रीम को पाइप करना

pipeThrough() ReadableStream इंटरफ़ेस का तरीका, मौजूदा स्ट्रीम को आपस में जोड़ने का चेन वाला तरीका देता है ट्रांसफ़ॉर्म स्ट्रीम या पढ़ने लायक किसी भी अन्य जोड़े के ज़रिए किया जा सकता है. आम तौर पर, किसी स्ट्रीम को पाइप करने से वह लॉक हो जाता है पाइप की अवधि तक ही रखता है, ताकि अन्य पाठक उसे लॉक न कर सकें.

const transformStream = new TransformStream({
  transform(chunk, controller) {
    console.log('[transform]', chunk);
    controller.enqueue(new TextEncoder().encode(chunk));
  },
  flush(controller) {
    console.log('[flush]');
    controller.terminate();
  },
});

const readableStream = new ReadableStream({
  start(controller) {
    // called by constructor
    console.log('[start]');
    controller.enqueue('a');
    controller.enqueue('b');
    controller.enqueue('c');
  },
  pull(controller) {
    // called read when controller's queue is empty
    console.log('[pull]');
    controller.enqueue('d');
    controller.close(); // or controller.error();
  },
  cancel(reason) {
    // called when rs.cancel(reason)
    console.log('[cancel]', reason);
  },
});

(async () => {
  const reader = readableStream.pipeThrough(transformStream).getReader();
  for (let result = await reader.read(); !result.done; result = await reader.read()) {
    console.log('[value]', result.value);
  }
})();

अगला कोड सैंपल (कुछ जानकारी शामिल नहीं है) आपको "शाउटिंग" लागू करने का तरीका दिखाता है fetch() का वर्शन जो जवाब के तौर पर दिए गए प्रॉमिस को सुनकर, पूरे टेक्स्ट को अंग्रेज़ी के बड़े अक्षरों में कर देता है स्ट्रीम के तौर पर और अपरकेसिंग डेटा को एक-एक करके करें. इस तरीके का लाभ यह है कि आपको जिससे पूरे दस्तावेज़ को डाउनलोड करना होता है. इससे बड़ी फ़ाइलों के साथ काम करते समय काफ़ी फ़र्क़ पड़ सकता है.

function upperCaseStream() {
  return new TransformStream({
    transform(chunk, controller) {
      controller.enqueue(chunk.toUpperCase());
    },
  });
}

function appendToDOMStream(el) {
  return new WritableStream({
    write(chunk) {
      el.append(chunk);
    }
  });
}

fetch('./lorem-ipsum.txt').then((response) =>
  response.body
    .pipeThrough(new TextDecoderStream())
    .pipeThrough(upperCaseStream())
    .pipeTo(appendToDOMStream(document.body))
);

डेमो

नीचे दिए गए डेमो में बताया गया है कि किस तरह की लाइव स्ट्रीम आसानी से पढ़ी जा सकती हैं, उसमें कितनी बदलाव की जा सकती है, और उसमें बदलाव कैसे किया जा सकता है. इसमें वे उदाहरण भी शामिल हैं pipeThrough() और pipeTo() पाइप चेन के बराबर है. साथ ही, tee() के डेटा को भी दिखाता है. आपके पास इसे चलाने का विकल्प है डेमो को खुद की विंडो में या सोर्स कोड.

ब्राउज़र में उपलब्ध उपयोगी स्ट्रीम

इस ब्राउज़र में कई काम की स्ट्रीम पहले से मौजूद होती हैं. इस टूल की मदद से, ब्लॉब से ReadableStream लिया गया है. Blob इंटरफ़ेस का stream() तरीका दिखता है एक ReadableStream, जो पढ़ने पर BLOB में मौजूद डेटा को दिखाता है. साथ ही, याद रखें कि File ऑब्जेक्ट, एक खास टाइप का Blob के साथ ही, इसे किसी भी कॉन्टेक्स्ट में इस्तेमाल किया जा सकता है.

const readableStream = new Blob(['hello world'], { type: 'text/plain' }).stream();

TextDecoder.decode() और TextEncoder.encode() के स्ट्रीमिंग वर्शन कॉल किए जाते हैं TextDecoderStream और TextEncoderStream का इस्तेमाल किया जाएगा.

const response = await fetch('https://streams.spec.whatwg.org/');
const decodedStream = response.body.pipeThrough(new TextDecoderStream());

फ़ाइल को कंप्रेस या डीकंप्रेस करना आसान है. CompressionStream और DecompressionStream स्ट्रीम बदल दें क्रम से. नीचे दिए गए कोड सैंपल में, स्ट्रीम की खास जानकारी डाउनलोड करने और उसे कंप्रेस (gzip) करने का तरीका बताया गया है ठीक ब्राउज़र में, और कंप्रेस की गई फ़ाइल को सीधे डिस्क पर लिखें.

const response = await fetch('https://streams.spec.whatwg.org/');
const readableStream = response.body;
const compressedStream = readableStream.pipeThrough(new CompressionStream('gzip'));

const fileHandle = await showSaveFilePicker();
const writableStream = await fileHandle.createWritable();
compressedStream.pipeTo(writableStream);

File System Access API की FileSystemWritableFileStream और प्रयोगात्मक fetch() अनुरोध स्ट्रीम जंगल में ऐसी धाराओं के उदाहरण जो लिखने में मदद करते हैं.

सीरियल एपीआई, पढ़ने लायक और लिखने लायक, दोनों तरह की स्ट्रीम का ज़्यादा इस्तेमाल करता है.

// Prompt user to select any serial port.
const port = await navigator.serial.requestPort();
// Wait for the serial port to open.
await port.open({ baudRate: 9_600 });
const reader = port.readable.getReader();

// Listen to data coming from the serial device.
while (true) {
  const { value, done } = await reader.read();
  if (done) {
    // Allow the serial port to be closed later.
    reader.releaseLock();
    break;
  }
  // value is a Uint8Array.
  console.log(value);
}

// Write to the serial port.
const writer = port.writable.getWriter();
const data = new Uint8Array([104, 101, 108, 108, 111]); // hello
await writer.write(data);
// Allow the serial port to be closed later.
writer.releaseLock();

आखिर में, WebSocketStream एपीआई, स्ट्रीम को WebSocket API के साथ इंटिग्रेट करता है.

const wss = new WebSocketStream(WSS_URL);
const { readable, writable } = await wss.connection;
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);
}

काम के संसाधन

स्वीकार की गई

इस लेख की समीक्षा इन्होंने की है जेक आर्किबाल्ड, फ़्रांसुआ बोफ़र्ट, सैम डटन, मैटियास ब्यूलेन्स, Surma, जो मेडली और ऐडम राइस. जेक आर्किबाल्ड की ब्लॉग पोस्ट से, मुझे काफ़ी मदद मिली स्ट्रीम. कुछ कोड सैंपल, GitHub के उपयोगकर्ता से प्रेरित हैं @bellbind के एक्सप्लोरेशन और प्रोज़ के हिस्से, स्ट्रीम पर MDN वेब दस्तावेज़. कॉन्टेंट बनाने Streams Standard's लेखकों ने शानदार काम किया है को लिखना होगा. रायन लारा की हीरो इमेज: अनस्प्लैश.