From 5f485f0b78299245ca16d654c20f3fee2d759972 Mon Sep 17 00:00:00 2001 From: Hamish Willee Date: Tue, 1 Aug 2023 17:26:25 +1000 Subject: [PATCH 1/6] ReadableStream.from() static method --- .../api/readablestream/from_static/index.md | 84 +++++++++++++++++++ files/en-us/web/api/readablestream/index.md | 5 ++ 2 files changed, 89 insertions(+) create mode 100644 files/en-us/web/api/readablestream/from_static/index.md diff --git a/files/en-us/web/api/readablestream/from_static/index.md b/files/en-us/web/api/readablestream/from_static/index.md new file mode 100644 index 000000000000000..50821db753171e9 --- /dev/null +++ b/files/en-us/web/api/readablestream/from_static/index.md @@ -0,0 +1,84 @@ +--- +title: "ReadableStream: from() static method" +short-title: from() +slug: Web/API/ReadableStream/from_static +page-type: web-api-static-method +status: + - experimental +browser-compat: api.ReadableStream.from_static +--- + +{{APIRef("Streams")}}{{SeeCompatTable}} + +The **`ReadableStream.from()`** static method returns a {{domxref("ReadableStream")}} from a provided iterable or async iterable object. + +The method can be used to wrap iterable and async iterable objects as readable streams, including arrays, sets, async generators, `ReadableStreams`, Node.js `readable` streams, and so on. + +## Syntax + +```js-nolint +ReadableStream.from(anyIterable) +``` + +### Parameters + +- `anyIterable` + - : An [iterable](/en-US/docs/Web/JavaScript/Reference/Iteration_protocols#the_iterable_protocol) or [async iterable](/en-US/docs/Web/JavaScript/Reference/Iteration_protocols#the_async_iterator_and_async_iterable_protocols) object. + +### Return value + +A {{domxref("ReadableStream")}}. + +### Exceptions + +- {{jsxref("TypeError")}} + - : Thrown if the passed parameter is not an iterable or async iterable (does not define the `@@iterator` or `@@asyncIterator` method). + Also thrown if, during iteration, the result of the next step is not an object or is a promise that does not resolve to an object. + +### Examples + +```html hidden +

+```
+
+```js hidden
+const logElement = document.getElementById("log");
+function log(text) {
+  logElement.innerText += `${text}\n`;
+}
+```
+
+```js
+const asyncIterator = (async function* () {
+  yield 1;
+  yield 2;
+  yield 3;
+})();
+
+let myReadableStream = ReadableStream.from(asyncIterator);
+consumeStream(myReadableStream);
+
+// Iterate a ReadableStream asynchronously
+async function consumeStream(readableStream) {
+  for await (const chunk of myReadableStream) {
+    // Do something with each chunk
+    // Here we just log the values
+    log(`chunk: ${chunk}`);
+  }
+}
+```
+
+{{EmbedLiveSample("Examples")}}
+
+## Specifications
+
+{{Specifications}}
+
+## Browser compatibility
+
+{{Compat}}
+
+## See also
+
+- {{domxref("ReadableStream")}}
+- [Using readable streams](/en-US/docs/Web/API/Streams_API/Using_readable_streams)
diff --git a/files/en-us/web/api/readablestream/index.md b/files/en-us/web/api/readablestream/index.md
index b94d5fec7624f7f..eb00dbe39e9c755 100644
--- a/files/en-us/web/api/readablestream/index.md
+++ b/files/en-us/web/api/readablestream/index.md
@@ -21,6 +21,11 @@ The `ReadableStream` interface of the [Streams API](/en-US/docs/Web/API/Streams_
 - {{domxref("ReadableStream.locked")}} {{ReadOnlyInline}}
   - : Returns a boolean indicating whether or not the readable stream is locked to a reader.
 
+## Static methods
+
+- {{domxref("ReadableStream/from_static", "ReadableStream.from()")}} {{Experimental_Inline}}
+  - : Returns `ReadableStream` from a provided iterable or async iterable object, such as an array, a set, an async generator, and so on.
+
 ## Instance methods
 
 - {{domxref("ReadableStream.cancel()")}}

From 4779a71fe4f28fbd9a3be7081315fa2e93bc0d18 Mon Sep 17 00:00:00 2001
From: Hamish Willee 
Date: Mon, 7 Aug 2023 13:08:55 +1000
Subject: [PATCH 2/6] Improve example

---
 .../api/readablestream/from_static/index.md   | 74 ++++++++++++++++++-
 1 file changed, 71 insertions(+), 3 deletions(-)

diff --git a/files/en-us/web/api/readablestream/from_static/index.md b/files/en-us/web/api/readablestream/from_static/index.md
index 50821db753171e9..c872b6bf8207abb 100644
--- a/files/en-us/web/api/readablestream/from_static/index.md
+++ b/files/en-us/web/api/readablestream/from_static/index.md
@@ -35,7 +35,11 @@ A {{domxref("ReadableStream")}}.
   - : Thrown if the passed parameter is not an iterable or async iterable (does not define the `@@iterator` or `@@asyncIterator` method).
     Also thrown if, during iteration, the result of the next step is not an object or is a promise that does not resolve to an object.
 
-### Examples
+## Examples
+
+### Convert an async iterator to a ReadableStream
+
+This live example demonstrates how you can convert an async iterable to a `ReadableStream`, and then how this stream might be consumed.
 
 ```html hidden
 

@@ -46,16 +50,77 @@ const logElement = document.getElementById("log");
 function log(text) {
   logElement.innerText += `${text}\n`;
 }
+
+if (!ReadableStream.from) {
+  log("ReadableStream.from() is not supported");
+}
 ```
 
+The async iterable is an anonymous generator function that yields the values of 1, 2 and 3 when it is called three times.
+This is passed to `ReadableStream.from()` to create the `ReadableStream`.
+
 ```js
+// Define an asynchronous iterator
 const asyncIterator = (async function* () {
   yield 1;
   yield 2;
   yield 3;
 })();
 
-let myReadableStream = ReadableStream.from(asyncIterator);
+// Create ReadableStream from iterator
+const myReadableStream = ReadableStream.from(asyncIterator);
+```
+
+[Using readable streams](/en-US/docs/Web/API/Streams_API/Using_readable_streams) demonstrates several ways to consume a stream.
+The code below uses a `for ... await` loop, as this method is the simplest.
+Each iteration of the loop logs the current chunk from the stream.
+
+```js
+consumeStream(myReadableStream);
+
+// Iterate a ReadableStream asynchronously
+async function consumeStream(readableStream) {
+  for await (const chunk of myReadableStream) {
+    // Do something with each chunk
+    // Here we just log the values
+    log(`chunk: ${chunk}`);
+  }
+}
+```
+
+The output of consuming the stream is shown below (if `ReadableStream.from()` is supported).
+
+{{EmbedLiveSample("Convert an async iterator to a ReadableStream","100%", "80")}}
+
+### Convert an Array to a ReadableStream
+
+This example demonstrates how you can convert an `Array`to a `ReadableStream`.
+The iterable is just an array of strings that is passed to `ReadableStream.from()` to create the `ReadableStream`.
+
+```html hidden
+

+```
+
+```js hidden
+const logElement = document.getElementById("log");
+function log(text) {
+  logElement.innerText += `${text}\n`;
+}
+
+if (!ReadableStream.from) {
+  log("ReadableStream.from() is not supported");
+}
+```
+
+```js
+// An Array of vegetable names
+const vegetables = ["Carrot", "Broccoli", "Tomato", "Spinach"];
+
+// Create ReadableStream from the Array
+const myReadableStream = ReadableStream.from(vegetables);
+```
+
+```js hidden
 consumeStream(myReadableStream);
 
 // Iterate a ReadableStream asynchronously
@@ -68,7 +133,10 @@ async function consumeStream(readableStream) {
 }
 ```
 
-{{EmbedLiveSample("Examples")}}
+We use the same approach as in the previous example to consume the stream (see previous section).
+The output is shown below.
+
+{{EmbedLiveSample("Convert an Array to a ReadableStream","100%", "100")}}
 
 ## Specifications
 

From fca16cf86f2b1dab71f8f7480a68d66d9eb245be Mon Sep 17 00:00:00 2001
From: Hamish Willee 
Date: Mon, 7 Aug 2023 14:20:08 +1000
Subject: [PATCH 3/6] Fix up ReadableStream example of converting item to
 readable stream

---
 files/en-us/web/api/readablestream/index.md | 12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/files/en-us/web/api/readablestream/index.md b/files/en-us/web/api/readablestream/index.md
index eb00dbe39e9c755..ac4cf2c1fc13654 100644
--- a/files/en-us/web/api/readablestream/index.md
+++ b/files/en-us/web/api/readablestream/index.md
@@ -117,9 +117,15 @@ fetch("https://www.example.org")
   });
 ```
 
-### Convert async iterator to stream
+### Convert an iterator or async iterator to a stream
 
-Converting an [(async) iterator](/en-US/docs/Web/JavaScript/Guide/Iterators_and_generators) to a readable stream:
+The {{domxref("ReadableStream/from_static", "from()")}} static method can convert an iterator, such as an {{jsxref("Array")}} or {{jsxref("Map")}}, or an [(async) iterator](/en-US/docs/Web/JavaScript/Guide/Iterators_and_generators) to a readable stream:
+
+```js
+const myReadableStream = ReadableStream.from(iteratorOrAsyncIterator);
+```
+
+On browsers that don't support the `from()` method you can instead create your own [custom readable stream](/en-US/docs/Web/API/Streams_API/Using_readable_streams#creating_your_own_custom_readable_stream) to do the achieve the same result:
 
 ```js
 function iteratorToStream(iterator) {
@@ -137,8 +143,6 @@ function iteratorToStream(iterator) {
 }
 ```
 
-This works with both async and non-async iterators.
-
 ### Async iteration of a stream using for await...of
 
 This example shows how you can process the `fetch()` response using a [`for await...of`](/en-US/docs/Web/JavaScript/Reference/Statements/for-await...of) loop to iterate through the arriving chunks.

From 71ab25c09790c9ec7cb97c09c4f9df9111b8aa4d Mon Sep 17 00:00:00 2001
From: Hamish Willee 
Date: Mon, 7 Aug 2023 14:46:22 +1000
Subject: [PATCH 4/6] Fix up typo

---
 files/en-us/web/api/readablestream/from_static/index.md | 2 +-
 files/en-us/web/api/readablestream/index.md             | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/files/en-us/web/api/readablestream/from_static/index.md b/files/en-us/web/api/readablestream/from_static/index.md
index c872b6bf8207abb..c68b91e435a403c 100644
--- a/files/en-us/web/api/readablestream/from_static/index.md
+++ b/files/en-us/web/api/readablestream/from_static/index.md
@@ -12,7 +12,7 @@ browser-compat: api.ReadableStream.from_static
 
 The **`ReadableStream.from()`** static method returns a {{domxref("ReadableStream")}} from a provided iterable or async iterable object.
 
-The method can be used to wrap iterable and async iterable objects as readable streams, including arrays, sets, async generators, `ReadableStreams`, Node.js `readable` streams, and so on.
+The method can be used to wrap iterable and async iterable objects as readable streams, including arrays, sets, arrays of promises, async generators, `ReadableStreams`, Node.js `readable` streams, and so on.
 
 ## Syntax
 
diff --git a/files/en-us/web/api/readablestream/index.md b/files/en-us/web/api/readablestream/index.md
index ac4cf2c1fc13654..085df05c0419683 100644
--- a/files/en-us/web/api/readablestream/index.md
+++ b/files/en-us/web/api/readablestream/index.md
@@ -125,7 +125,7 @@ The {{domxref("ReadableStream/from_static", "from()")}} static method can conver
 const myReadableStream = ReadableStream.from(iteratorOrAsyncIterator);
 ```
 
-On browsers that don't support the `from()` method you can instead create your own [custom readable stream](/en-US/docs/Web/API/Streams_API/Using_readable_streams#creating_your_own_custom_readable_stream) to do the achieve the same result:
+On browsers that don't support the `from()` method you can instead create your own [custom readable stream](/en-US/docs/Web/API/Streams_API/Using_readable_streams#creating_your_own_custom_readable_stream) to achieve the same result:
 
 ```js
 function iteratorToStream(iterator) {

From 9cbcb4664d2a05530feef3571682227a6a1cde81 Mon Sep 17 00:00:00 2001
From: Hamish Willee 
Date: Mon, 7 Aug 2023 16:01:00 +1000
Subject: [PATCH 5/6] Fix typo

---
 files/en-us/web/api/readablestream/from_static/index.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/files/en-us/web/api/readablestream/from_static/index.md b/files/en-us/web/api/readablestream/from_static/index.md
index c68b91e435a403c..34754591b305d62 100644
--- a/files/en-us/web/api/readablestream/from_static/index.md
+++ b/files/en-us/web/api/readablestream/from_static/index.md
@@ -72,7 +72,7 @@ const myReadableStream = ReadableStream.from(asyncIterator);
 ```
 
 [Using readable streams](/en-US/docs/Web/API/Streams_API/Using_readable_streams) demonstrates several ways to consume a stream.
-The code below uses a `for ... await` loop, as this method is the simplest.
+The code below uses a `for ...await` loop, as this method is the simplest.
 Each iteration of the loop logs the current chunk from the stream.
 
 ```js

From 9df30b6ab02f9c51ac01cb7e31121d6ae668a09b Mon Sep 17 00:00:00 2001
From: Hamish Willee 
Date: Mon, 21 Aug 2023 10:54:46 +1000
Subject: [PATCH 6/6] Add in sections for example

---
 .../api/readablestream/from_static/index.md   | 30 +++++++++++++++----
 1 file changed, 25 insertions(+), 5 deletions(-)

diff --git a/files/en-us/web/api/readablestream/from_static/index.md b/files/en-us/web/api/readablestream/from_static/index.md
index 34754591b305d62..9bd6369e0dbbcb2 100644
--- a/files/en-us/web/api/readablestream/from_static/index.md
+++ b/files/en-us/web/api/readablestream/from_static/index.md
@@ -41,16 +41,28 @@ A {{domxref("ReadableStream")}}.
 
 This live example demonstrates how you can convert an async iterable to a `ReadableStream`, and then how this stream might be consumed.
 
-```html hidden
+#### HTML
+
+The HTML is consists of single `
` element, which is used for logging.
+
+```html
 

 ```
 
-```js hidden
+#### JavaScript
+
+The example code creates a `log()` function to write to the log HTML element.
+
+```js
 const logElement = document.getElementById("log");
 function log(text) {
   logElement.innerText += `${text}\n`;
 }
+```
+
+It then checks if the static method is supported, and if not, logs the result.
 
+```js
 if (!ReadableStream.from) {
   log("ReadableStream.from() is not supported");
 }
@@ -88,14 +100,15 @@ async function consumeStream(readableStream) {
 }
 ```
 
+#### Result
+
 The output of consuming the stream is shown below (if `ReadableStream.from()` is supported).
 
 {{EmbedLiveSample("Convert an async iterator to a ReadableStream","100%", "80")}}
 
 ### Convert an Array to a ReadableStream
 
-This example demonstrates how you can convert an `Array`to a `ReadableStream`.
-The iterable is just an array of strings that is passed to `ReadableStream.from()` to create the `ReadableStream`.
+This example demonstrates how you can convert an `Array` to a `ReadableStream`.
 
 ```html hidden
 

@@ -112,6 +125,10 @@ if (!ReadableStream.from) {
 }
 ```
 
+#### JavaScript
+
+The iterable is just an array of strings that is passed to `ReadableStream.from()` to create the `ReadableStream`.
+
 ```js
 // An Array of vegetable names
 const vegetables = ["Carrot", "Broccoli", "Tomato", "Spinach"];
@@ -133,7 +150,10 @@ async function consumeStream(readableStream) {
 }
 ```
 
-We use the same approach as in the previous example to consume the stream (see previous section).
+We use the same approach as in the previous example log and to consume the stream, so that is not shown here.
+
+#### Result
+
 The output is shown below.
 
 {{EmbedLiveSample("Convert an Array to a ReadableStream","100%", "100")}}