AJAX- Streams

Streams allow you to process data bit by bit on-the-fly as it is being transferred. In other words, you don't have to download the entire file first to process the data.

This processes an image as it is being fetched from the server. Besides .getReader(), you can also use .pipeThrough() and pipeTo() through/to connect to a given Stream, and .tee() to branch into two ReadableStream instances.
RESETRUNFULL
<!DOCTYPE><html><body>
   <img height="2000" />
   <script>
      const image = document.querySelector('img');
      fetch('./shared/big_file.jpg')
      .then(response => response.body)
      .then(rs => {
         const reader = rs.getReader();
         return new ReadableStream({
            async start(controller) {
               while (true) {
                  const { done, value } = await reader.read();
                  // process value here
                  if (done) break;
                  controller.enqueue(value);
               }
               controller.close();
               reader.releaseLock();
            }
         })
      })
      .then(rs => new Response(rs))
      .then(response => response.blob())
      .then(blob => URL.createObjectURL(blob))
      .then(url => image.src = url)
      .catch(console.error);
   </script>
</body></html>
This processes a string over a WritableStream.
RESETRUNFULL
<!DOCTYPE><html><body>
   <ul />
   <script>
      const list = document.querySelector('ul');
      function sendMessage(message, writableStream) {  // defaultWriter is of type WritableStreamDefaultWriter
         const defaultWriter = writableStream.getWriter();
         const encoder = new TextEncoder();
         const encoded = encoder.encode(message,  { stream: true });
         encoded.forEach((chunk) => {
            defaultWriter.ready.then(() => {
               return defaultWriter.write(chunk);
            }).then(() => {
              console.log("Chunk written to sink.");
            }).catch((err) => {
              console.log("Chunk error:", err);
            });
         });  // Call ready again to ensure that all chunks are written before closing the writer.
         defaultWriter.ready.then(() => {
            defaultWriter.close();
         }).then(() => {
            console.log("All chunks written");
         }).catch((err) => {
            console.log("Stream error:", err);
         });
      }
      const decoder = new TextDecoder("utf-8");
      const queuingStrategy = new CountQueuingStrategy({ highWaterMark: 1 });
      let result = "";
      const writableStream = new WritableStream({  // Implement the sink
         write(chunk) {
            return new Promise((resolve, reject) => {
               var buffer = new ArrayBuffer(2);
               var view = new Uint16Array(buffer);
               view[0] = chunk-1;  // c->b, b->a etc.
               var decoded = decoder.decode(view, { stream: true });
               var listItem = document.createElement('li');
               listItem.textContent = "Chunk decoded: " + decoded;
               list.appendChild(listItem);
               result += decoded;
              resolve();
            });
         },
         close() {
            var listItem = document.createElement('li');
            listItem.textContent = "[MESSAGE RECEIVED] " + result;
            list.appendChild(listItem);
         },
         abort(err) {
            console.log("Sink error:", err);
         }
      }, queuingStrategy);
      sendMessage("Ifmmp-!xpsme/", writableStream);
   </script>
</body></html>