Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Document “AsyncGenerator” & “AsyncGeneratorFunction” #2861

Closed
wants to merge 23 commits into from
Closed
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
6de1a35
Document “AsyncGenerator” & “AsyncGeneratorFunction”
DerekNonGeneric Mar 4, 2021
a8d56b1
fixup: use one <code> per argument in param definition
DerekNonGeneric Mar 4, 2021
ef06d6e
fixup: pair `.notecard` w/ `.note`s
DerekNonGeneric Mar 4, 2021
c1a2f09
fixup: format Note sections w/ headings
DerekNonGeneric Mar 4, 2021
cff7b5d
fixup: `JSxRef` -> `jsxref`
DerekNonGeneric Mar 4, 2021
d38696c
fixup: improve description for AsyncGenerator.prototype.throw()
DerekNonGeneric Mar 5, 2021
77c1e75
fixup: improve naming & var -> const in constructor example
DerekNonGeneric Mar 5, 2021
15a51eb
fixup: improve See_also for AsynGeneratorFunction
DerekNonGeneric Mar 5, 2021
658a2b4
fixup: improve See_also for AsynGenerator
DerekNonGeneric Mar 5, 2021
ccfa77d
fixup: use multiline syntax notation instead of square bracket notation
DerekNonGeneric Mar 5, 2021
dddfb8a
async review
Rumyra Mar 9, 2021
ee4aca0
fixup: modify AsyncGeneratorFunction example to work w/o TLA
DerekNonGeneric Mar 12, 2021
033ba8f
add AsyncGenerator methods & update code sample variable names
DerekNonGeneric Mar 13, 2021
1ab12a5
statement operator
Rumyra Mar 23, 2021
76a0bb5
working on statement
Rumyra Mar 24, 2021
d58fe42
Update files/en-us/web/javascript/reference/operators/async_function_…
Rumyra Mar 25, 2021
c331788
rel notes
Rumyra Jul 14, 2021
c6f5f6e
Merge branch 'main' into feat/add-missing-ctrl-abstr-pages
Rumyra Jul 14, 2021
cf479a0
tidying up async gen docs
Rumyra Jul 14, 2021
0c8af2e
Revert "rel notes"
Rumyra Jul 14, 2021
0d1ab7a
Update files/en-us/web/javascript/reference/global_objects/asyncgener…
Rumyra Aug 3, 2021
f0be1e2
Update files/en-us/web/javascript/reference/global_objects/asyncgener…
Rumyra Aug 3, 2021
0786efa
working on it
Rumyra Aug 6, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
---
title: AsyncGenerator
slug: Web/JavaScript/Reference/Global_Objects/AsyncGenerator
tags:
- Class
- ECMAScript 2018
- Generator
- JavaScript
- Async Generator
- Async Iterator
- Reference
browser-compat: javascript.builtins.AsyncGenerator
---
<div>{{JSRef}}</div>

<p>The <code><strong>AsyncGenerator</strong></code> object is returned by an {{jsxref("Statements/async_function*", "async generator function")}} and it conforms to both the <a href="/en-US/docs/Web/JavaScript/Reference/Iteration_protocols#The_iterable_protocol">iterable protocol</a> and the <a href="/en-US/docs/Web/JavaScript/Reference/Iteration_protocols#The_iterator_protocol">iterator protocol</a>.</p>
Rumyra marked this conversation as resolved.
Show resolved Hide resolved

<h2 id="Constructor">Constructor</h2>

<p>This object cannot be instantiated directly. Instead, an <code>AsyncGenerator</code> instance can be returned from an {{jsxref("Statements/async_function*", "async generator function")}}:</p>
Rumyra marked this conversation as resolved.
Show resolved Hide resolved

<p>Async generators always yield a {{jsxref("Promise")}} object.</p>

<pre class="brush: js">async function* createAsyncGenerator() {
DerekNonGeneric marked this conversation as resolved.
Show resolved Hide resolved
yield await Promise.resolve(1);
yield await Promise.resolve(2);
yield await Promise.resolve(3);
}

const asyncGen = createAsyncGenerator(); // "AsyncGenerator { }"

asyncGen.next()
.then(res => console.log(res.value)); // 1
asyncGen.next()
.then(res => console.log(res.value)); // 2
asyncGen.next()
.then(res => console.log(res.value)); // 3</pre>

<h2 id="Instance_methods">Instance methods</h2>

<dl>
<dt>{{jsxref("AsyncGenerator.prototype.next()")}}</dt>
<dd>Returns a {{jsxref("Promise")}} which will be resolved with the given value yielded by the {{jsxref("Operators/yield", "yield")}} expression.</dd>
<dt>{{jsxref("AsyncGenerator.prototype.return()")}}</dt>
<dd>Returns a {{jsxref("Promise")}} which will be resolved with the given value yielded by the {{jsxref("Operators/yield", "yield")}} expression and finishes the generator.</dd>
<dt>{{jsxref("AsyncGenerator.prototype.throw()")}}</dt>
<dd>Returns a {{jsxref("Promise")}} that is rejected with an exception thrown from (or uncaught from) within the async generator function and finishes the generator unless the exception is caught within that generator.</dd>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a long and complicated sentence and could do with splitting into 2, probably at the "function and finishes" juncture. It's also not very clear how to parse "(or uncaught from)" or how that relates to "unless the exception is caught within that generator".

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Talking about next and finishes make me think, whether a state chart might be helpful for comprehension.

</dl>

<h2 id="Examples">Examples</h2>

<h3 id="async_generator_iteration">Async generator iteration</h3>

<p>The following example iterates over an async generator logging values 1 - 6 to the console, at decreasing time intervals.</p>

<pre class="brush: js;">
function waitFor(time, value) {
return new Promise((resolve, reject) => {
setTimeout(() => resolve(value), time);
});
}

async function* generate() {
yield await waitFor(1000, 1);
yield await waitFor(2000, 2);
yield await waitFor(400, 3);
yield await waitFor(800, 4);
yield await waitFor(150, 5);
yield await waitFor(50, 6);
console.log('All done!');
}

async function main() {
for await (const value of generate()) {
console.log('value', value);
}
}

main()
.catch((e) => console.error('error', e));</pre>

<h2 id="Specifications">Specifications</h2>

{{Specifications}}

<h2 id="Browser_compatibility">Browser compatibility</h2>

<p>{{Compat}}</p>

<h2 id="See_also">See also</h2>

<ul>
<li>{{jsxref("Statements/function*", "function*")}}</li>
<li>{{jsxref("Statements/async_function*", "async function*")}}</li>
<li>{{jsxref("Operators/function*", '<code>function*</code> expression', "", 1)}}</li>
<li>{{jsxref("GeneratorFunction")}}</li>
<li>{{jsxref("AsyncGeneratorFunction")}}</li>
<li><a href="/en-US/docs/Web/JavaScript/Guide/The_Iterator_protocol">The Iterator protocol</a></li>
</ul>
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
---
title: AsyncGenerator.prototype.next()
slug: Web/JavaScript/Reference/Global_Objects/AsyncGenerator/next
tags:
- ECMAScript 2018
- AsyncGenerator
- JavaScript
- Method
- Prototype
- Reference
browser-compat: javascript.builtins.AsyncGenerator.next
---
<div>{{JSRef}}</div>

<p><span class="seoSummary">The <strong><code>next()</code></strong> method returns an object with two properties <code>done</code> and <code>value</code>. You can also provide a parameter to the <code>next</code> method to send a value to the generator.</span></p>
Rumyra marked this conversation as resolved.
Show resolved Hide resolved

<h2 id="Syntax">Syntax</h2>

<pre class="brush: js"><var>asyncGen</var>.next(<var>value</var>)</pre>

<h3 id="Parameters">Parameters</h3>

<dl>
<dt><code><var>value</var></code></dt>
<dd>The value to send to the generator.</dd>
<dd>The value will be assigned as a result of a <code>yield</code> expression. For example, in <code><var>variable</var> = yield <var>expression</var></code>, the value passed to the <code>.next()</code> function will be assigned to <code><var>variable</var></code>.</dd>
Rumyra marked this conversation as resolved.
Show resolved Hide resolved
</dl>

<h3 id="Return_value">Return value</h3>

<p>An {{jsxref("Object")}} with two properties:</p>
Rumyra marked this conversation as resolved.
Show resolved Hide resolved

<dl>
<dt><code>done</code> (boolean)</dt>
Rumyra marked this conversation as resolved.
Show resolved Hide resolved
<dd>Has the value <code>true</code> if the iterator is past the end of the iterated sequence. In this case <code>value</code> optionally specifies the <em>return value</em> of the iterator.</dd>
<dd>Has the value <code>false</code> if the iterator was able to produce the next value in the sequence. This is equivalent of not specifying the <code>done</code> property altogether.</dd>
<dt><code>value</code></dt>
<dd>Any JavaScript value returned by the iterator. Can be omitted when <code>done</code> is <code>true</code>.</dd>
</dl>

<h2 id="Examples">Examples</h2>

<h3 id="Using_next">Using next()</h3>

<p>The following example shows a simple generator and the object that the <code>next</code> method returns:</p>

<pre class="brush: js">async function* createAsyncGenerator() {
yield await Promise.resolve(1);
yield await Promise.resolve(2);
yield await Promise.resolve(3);
}

const asyncGen = createAsyncGenerator(); // "AsyncGenerator { }"
Rumyra marked this conversation as resolved.
Show resolved Hide resolved
asyncGen.next().then(res => console.log(res)); // "Object { value: 1, done: false }"
asyncGen.next().then(res => console.log(res)); // "Object { value: 2, done: false }"
asyncGen.next().then(res => console.log(res)); // "Object { value: 3, done: false }"
asyncGen.next().then(res => console.log(res)); // "Object { value: undefined, done: true }"
</pre>

<h3 id="Using_next_with_a_list">Using next() with a list</h3>

<pre class="brush: js">async function* getPage(pageSize = 1, list) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a bit of a complex example that could benefit from a paragraph explaining what it's doing.

let output = [];
let index = 0;

while (index &lt; list.length) {
output = [];
for (let i = index; i &lt; index + pageSize; i++) {
if (list[i]) {
output.push(list[i]);
}
}

yield await Promise.resolve(output);
index += pageSize;
}
}

const list = [1, 2, 3, 4, 5, 6, 7, 8];
const page = getPage(3, list); // AsyncGenerator { }

page.next().then(res => console.log(res)); // Object { value: [1, 2, 3], done: false }
page.next().then(res => console.log(res)); // Object { value: [4, 5, 6], done: false }
page.next().then(res => console.log(res)); // Object { value: [7, 8], done: false }
page.next().then(res => console.log(res)); // Object { value: undefined, done: true }
</pre>

<h3 id="Sending_values_to_the_generator">Sending values to the generator</h3>

<p>In this example, <code>next</code> is called with a value.</p>

<p>Note that the first call does not log anything, because the generator was not yielding anything initially.</p>

<pre class="brush: js">async function* createAsyncGenerator() {
while (true) {
let value = yield await Promise.resolve(null);
console.log(value);
}
}

const asyncGen = createAsyncGenerator();
asyncGen.next(1).then(res => console.log(res));
// { value: null, done: false }
asyncGen.next(2).then(res => console.log(res));
// 2
// { value: null, done: false }
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here, you are mixing up the console.log output with the internal state.

Perhaps use // => 2 for logging output?

</pre>

<h2 id="Specifications">Specifications</h2>

{{Specifications}}

<h2 id="Browser_compatibility">Browser compatibility</h2>

<p>{{Compat}}</p>

<h2 id="See_also">See also</h2>

<ul>
<li>{{jsxref("Statements/async_function*", "async function*")}}</li>
Rumyra marked this conversation as resolved.
Show resolved Hide resolved
<li><a href="/en-US/docs/Web/JavaScript/Guide/Iterators_and_Generators">Iterators and generators</a></li>
</ul>
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
---
title: AsyncGenerator.prototype.return()
slug: Web/JavaScript/Reference/Global_Objects/AsyncGenerator/return
tags:
- ECMAScript 2018
- AsyncGenerator
- JavaScript
- Method
- Prototype
- Reference
browser-compat: javascript.builtins.AsyncGenerator.return
---
<div>{{JSRef}}</div>

<p>The <strong><code>return()</code></strong> method returns the given value and finishes the generator.</p>

<h2 id="Syntax">Syntax</h2>

<pre class="brush: js"><var>asyncGen</var>.return(<var>value</var>)</pre>

<h3 id="Parameters">Parameters</h3>

<dl>
<dt><code><var>value</var></code></dt>
<dd>The value to return.</dd>
</dl>

<h3 id="Return_value">Return value</h3>

<p>The value that is given as an argument.</p>
Rumyra marked this conversation as resolved.
Show resolved Hide resolved

<h2 id="Examples">Examples</h2>

<h3 id="Using_return">Using return()</h3>

<p>The following example shows a simple async generator and the <code>return</code> method.</p>

<pre class="brush: js">async function* createAsyncGenerator() {
yield await Promise.resolve(1);
yield await Promise.resolve(2);
yield await Promise.resolve(3);
}

const asyncGen = createAsyncGenerator();

asyncGen.next().then(res => console.log(res)); // { value: 1, done: false }
asyncGen.return('foo').then(res => console.log(res)); // { value: "foo", done: true }
asyncGen.next().then(res => console.log(res)); // { value: undefined, done: true }
</pre>

<p>If <code>return(<var>value</var>)</code> is called on a generator that is already in "completed" state, the generator will remain in "completed" state.</p>

<p>If no argument is provided, the <code>value</code> property of returned object is the same as if <code>.next()</code>. If an argument is provided, it will be set to the value of the <code>value</code> property of the returned object.</p>
Rumyra marked this conversation as resolved.
Show resolved Hide resolved

<pre class="brush: js">async function* createAsyncGenerator() {
yield await Promise.resolve(1);
yield await Promise.resolve(2);
yield await Promise.resolve(3);
}

const asyncGen = createAsyncGenerator();

asyncGen.next().then(res => console.log(res)); // { value: 1, done: false }
asyncGen.next().then(res => console.log(res)); // { value: 2, done: false }
asyncGen.next().then(res => console.log(res)); // { value: 3, done: false }
asyncGen.next().then(res => console.log(res)); // { value: undefined, done: true }
asyncGen.return().then(res => console.log(res)); // { value: undefined, done: true }
asyncGen.return(1).then(res => console.log(res)); // { value: 1, done: true }
</pre>

<h2 id="Specifications">Specifications</h2>

{{Specifications}}

<h2 id="Browser_compatibility">Browser compatibility</h2>

<p>{{Compat}}</p>

<h2 id="See_also">See also</h2>

<ul>
<li>{{jsxref("Statements/async_function*", "async function*")}}</li>
Rumyra marked this conversation as resolved.
Show resolved Hide resolved
<li><a href="/en-US/docs/Web/JavaScript/Guide/Iterators_and_Generators">Iterators and generators</a></li>
</ul>
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
---
title: AsyncGenerator.prototype.throw()
slug: Web/JavaScript/Reference/Global_Objects/AsyncGenerator/throw
tags:
- ECMAScript 2018
- AsyncGenerator
- JavaScript
- Method
- Prototype
- Reference
browser-compat: javascript.builtins.AsyncGenerator.throw
---
<div>{{JSRef}}</div>

<p><span class="seoSummary">The <strong><code>throw()</code></strong> method resumes the execution of a generator by throwing an error into it and returns an object with two properties <code>done</code> and <code>value</code>.</span></p>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The seoSummary can likely be omitted here as well for the same reason mentioned before.


<h2 id="Syntax">Syntax</h2>

<pre class="brush: js"><code><var>asyncGen</var>.throw(<var>exception</var>)</code></pre>
Rumyra marked this conversation as resolved.
Show resolved Hide resolved

<h3 id="Parameters">Parameters</h3>

<dl>
<dt><code><var>exception</var></code></dt>
<dd>The exception to throw. For debugging purposes, it is useful to make it an <code>instanceof</code> {{jsxref("Error")}}.</dd>
</dl>

<h3 id="Return_value">Return value</h3>

<p>An {{jsxref("Global_Objects/Object", "Object")}} with two properties:</p>

<dl>
<dt><code>done</code> (boolean)</dt>
Rumyra marked this conversation as resolved.
Show resolved Hide resolved
<dd>
<ul>
<li>Has the value <code>true</code> if the iterator is past the end of the iterated sequence. In this case <code>value</code> optionally specifies the <em>return value</em> of the iterator.</li>
<li>Has the value <code>false</code> if the iterator was able to produce the next value in the sequence. This is equivalent of not specifying the <code>done</code> property altogether.</li>
</ul>
</dd>
<dt><code>value</code></dt>
<dd>Any JavaScript value returned by the iterator. Can be omitted when <code>done</code> is <code>true</code>.</dd>
</dl>

<h2 id="Examples">Examples</h2>

<h3 id="Using_throw">Using throw()</h3>

<p>The following example shows a simple generator and an error that is thrown using the <code>throw</code> method. An error can be caught by a {{jsxref("Statements/try...catch", "try...catch")}} block as usual.</p>

<pre class="brush: js">async function* createAsyncGenerator() {
while(true) {
try {
yield 42;
} catch(e) {
console.log('Error caught!');
}
}
}

const asyncGen = createAsyncGenerator();
asyncGen.next(1).then(res => console.log(res));
// { value: 42, done: false }
asyncGen.throw(new Error('Something went wrong')).then(res => console.log(res));
// "Error caught!"
// { value: 42, done: false }
</pre>

<h2 id="Specifications">Specifications</h2>

{{Specifications}}

<h2 id="Browser_compatibility">Browser compatibility</h2>

<p>{{Compat}}</p>

<h2 id="See_also">See also</h2>

<ul>
<li>{{jsxref("Statements/async_function*", "async function*")}}</li>
Rumyra marked this conversation as resolved.
Show resolved Hide resolved
<li><a href="/en-US/docs/Web/JavaScript/Guide/Iterators_and_Generators">Iterators and generators</a></li>
</ul>
Loading