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 +--- + +
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.
+ +WritableStream
. Pass it a data destination, called a 'sink' in it's constructor as a literal.writableStreamInstance.getWriter()
to get a defaul writer.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.
+ +highwatermark
: Specifies the maximum amout of data that the WritableStream
can handle at once. When creating the WritableStream
instance, the second property passed to the constructor is a queuing strategy object. This object's constructor takes an object with a highwatermark
property. How highwatermark
is specified varies depending on the type of queuing strategy object.writer.ready
: Returns a promise that resolves whenever the underlying data sink is able to receive more data for writing. Check this before adding new data to the pipe and before closing the writer.write()
: The sink's write()
method must return a promise. This tells writer.ready()
when to return its promise.