diff --git a/streams/README.md b/streams/README.md new file mode 100755 index 0000000000..3d51f13a6d --- /dev/null +++ b/streams/README.md @@ -0,0 +1,8 @@ + +Stream Samples +=== + +See https://googlechrome.github.io/samples/streams/index.html for a live demo. + + +Learn more at https://www.chromestatus.com/feature/5928498656968704 diff --git a/streams/demo.js b/streams/demo.js new file mode 100644 index 0000000000..c65eef18d1 --- /dev/null +++ b/streams/demo.js @@ -0,0 +1,61 @@ +'use strict'; + +let result; +function getWritableStream(queuingStrategy) { + const decoder = new TextDecoder("utf-8"); + result = ""; + return new WritableStream({ + // Implement the sink + write(chunk) { + return new Promise((resolve, reject) => { + let buffer = new ArrayBuffer(2); + let view = new Uint16Array(buffer); + view[0] = chunk; + let decoded = decoder.decode(view, {stream: true}); + ChromeSamples.log("Chunk decoded: " + decoded); + result += decoded + resolve(); + }); + }, + close() { + result = "[MESSAGE RECEIVED] " + result; + ChromeSamples.log(result); + }, + abort(e) { + ChromeSamples.log("[SINK] Error: " + e); + } + }, queuingStrategy); +} + +function sendMessage(message) { + // defaultWriter is of type WritableStreamDefaultWriter + const defaultWriter = writable.getWriter(); + const encoder = new TextEncoder(); + const encoded = encoder.encode(message, {stream: true}); + encoded.forEach(chunk => { + defaultWriter.ready + .then(() => { + defaultWriter.write(chunk) + .then(() => ChromeSamples.log("Chunk written to sink. 'defaultWriter.write()' promise resolved.")) + .catch(e => ChromeSamples.log("[CHUNK] Error: " + e)); + }); + }) + // Calling ready insures that all chunks are written to the sink before the writer is closed. + defaultWriter.ready + .then(() => { + defaultWriter.close() + .then(() => ChromeSamples.log("All chunks written. 'defaultWriter.close()' promise resolved.")) + .catch(e => ChromeSamples.log("[STREAM] Error: " + e)); + }); +} + +let writable; +document.querySelector('#sendMessage').addEventListener('click', function() { + // Clear the output from the previous call to sendMessage(). + ChromeSamples.clearLog(); + // Streams are only meant be used once. Get a stream for each message. + writable = getWritableStream(new CountQueuingStrategy({highWaterMark: 1})); + let message = document.querySelector('#input'); + sendMessage(message.value); + message.value = ""; +}) \ No newline at end of file diff --git a/streams/index.html b/streams/index.html new file mode 100755 index 0000000000..d372552abe --- /dev/null +++ b/streams/index.html @@ -0,0 +1,43 @@ +--- +feature_name: WritableStream +chrome_version: 59 +feature_id: 5928498656968704 +--- + +

Background

+

This sample illustrates the use of WritableStream, which shows how to break apart a longer piece of data and stream it (send it in chunks) to an output.

+ +

WritableStreams objects are designed to only be used once. This example creates a new instance every time "Send message" is clicked. The sendMessage() uses that instance to send every byte of the entered message and closes the instance when it is done (defaultWriter.close()).

+ +

The data flow in this example is generally from the text entry field to sink. The details are a bit more complicated. The general flow is this.

+ +
    +
  1. Create an instance of WritableStream. Pass it a data destination, called a 'sink' in it's constructor as a literal.
  2. +
  3. Call writableStreamInstance.getWriter() to get a defaul writer.
  4. +
  5. Iterate the chunks of the message and pass each to the default writer.
  6. +
  7. Close the default writer.
  8. +
+ +

If you're familliar at all with streams you may be wondering how backpressure is implemented using this API, especially since the word 'backpressure' doesn't appear as a member of any of the API's interfaces. Three items combine to create a backpressure signal.

+ + + +{% capture initial_output_content %} + +
+
+ + + +
+
+ +{% endcapture %} +{% include output_helper.html initial_output_content=initial_output_content %} + +{% include js_snippet.html filename='demo.js' %}