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 11 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,107 @@
---
title: AsyncGenerator
slug: Web/JavaScript/Reference/Global_Objects/AsyncGenerator
tags:
- Class
- ECMAScript 2018
- Generator
- JavaScript
- Async Generator
- Async Iterator
- Reference
---
<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>

<table class="standard-table">
<tbody>
<tr>
<th scope="col">Specification</th>
DerekNonGeneric marked this conversation as resolved.
Show resolved Hide resolved
</tr>
<tr>
<td>{{SpecName('ESDraft', '#sec-asyncgenerator-objects', 'AsyncGenerator objects')}}</td>
</tr>
</tbody>
</table>

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

<p>{{Compat("javascript.builtins.AsyncGenerator")}}</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,100 @@
---
title: AsyncGeneratorFunction
slug: Web/JavaScript/Reference/Global_Objects/AsyncGeneratorFunction
tags:
- Constructor
- ECMAScript 2018
- AsyncGeneratorFunction
- Iterator
- JavaScript
- Reference
---
<div>{{JSRef}}</div>

<p>The <strong><code>AsyncGeneratorFunction</code> constructor</strong> creates a new {{jsxref("Statements/async_function*", "async generator function", "", 1)}} object. In JavaScript, every async generator function is actually an <code>AsyncGeneratorFunction</code> object.</p>

<p>Note that <code>AsyncGeneratorFunction</code> is not a global object. It could be obtained by evaluating the following code.</p>
Copy link
Collaborator

Choose a reason for hiding this comment

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

Is this the recommended or normal way to use this feature?


<pre class="brush: js">Object.getPrototypeOf(async function*(){}).constructor
</pre>

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

<pre class="brush: js">new GeneratorFunction(functionBody)
new GeneratorFunction(arg1, functionBody)
new GeneratorFunction(arg1, arg2, functionBody)
</pre>

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

<dl>
<dt><code>arg1</code>, <code>arg2</code>, ... <code>arg<em>N</em></code></dt>
<dd>Names to be used by the function as formal argument names. Each must be a {{jsxref('String')}} that corresponds to a valid JavaScript identifier or a list of such strings separated with a comma; for example "<code>x</code>", "<code>theValue</code>", or "<code>a,b</code>".</dd>
Rumyra marked this conversation as resolved.
Show resolved Hide resolved
<dt><code>functionBody</code></dt>
<dd>A {{jsxref('String')}} containing the JavaScript statements comprising the function definition.
Copy link
Collaborator

Choose a reason for hiding this comment

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

Do eval()-type warnings apply here? I found I couldn't execute the example in the console because of the CSP.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Most likely.
This reads like a pendant to new Function() to be, which poses security vulnerabilities (esp. when running untrusted code).

</dd>
</dl>

<h2 id="Description">Description</h2>

<p>{{jsxref("Statements/async_function*", "async generator function")}} objects created with the <code>AsyncGeneratorFunction</code> constructor are parsed when the function is created. This is less efficient than declaring a generator function with an {{jsxref("Statements/async_function*", "async function* expression")}} and calling it within your code, because such functions are parsed with the rest of the code.</p>
Copy link
Collaborator

Choose a reason for hiding this comment

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

{{jsxref("Statements/async_function*", "async generator function")} is giving me broken links here and I guess elsewhere in the page.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Also if "async generator function" here is English, not an identifier (which I think it is) it should start with an uppercase letter.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Is {{jsxref("Statements/async_function*", "async function* expression")} intended to have the same target as {{jsxref("Statements/async_function*", "async generator function")}?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Also here and throughout this file,

{{jsxref("Statements/async_function*", "async generator function")}

should be

{{jsxref("Statements/async_function*", "async generator function", "", "1")}

to suppress code formatting, which isn't appropriate here. See https://github.com/mdn/yari/blob/main/kumascript/macros/jsxref.ejs#L10.


<p>All arguments passed to the function are treated as the names of the identifiers of the parameters in the function to be created, in the order in which they are passed.</p>
Copy link
Collaborator

Choose a reason for hiding this comment

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

Except for the final argument?


<div class="notecard note">
<h3>Note:</h3>
Rumyra marked this conversation as resolved.
Show resolved Hide resolved
<p>{{jsxref("Statements/async_generator_function*", "async generator functions")}} created with the <code>AsyncGeneratorFunction</code> constructor do not create closures to their creation contexts; they are always created in the global scope.</p>
Copy link
Collaborator

Choose a reason for hiding this comment

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

Again "async generator functions" should be "Async generator functions" if it's not an identifier.

Copy link
Collaborator

Choose a reason for hiding this comment

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

What does global scope refers to here (in context of an ES module, for example. Would other modules see it, as in, it were defined on window as property)?


<p>When running them, they will only be able to access their own local variables and global ones, not the ones from the scope in which the <code>AsyncGeneratorFunction</code> constructor was called.</p>

<p>This is different from using {{jsxref("Global_Objects/eval", "eval")}} with code for a generator function expression.</p>
</div>

<p>Invoking the <code>AsyncGeneratorFunction</code> constructor as a function (without using
the <code>new</code> operator) has the same effect as invoking it as a constructor.</p>

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

<h3 id="using_the_constructor">Using the constructor</h3>

<p>The following example uses the <code>AsyncGeneratorFunction</code> constructor to create an async generator function.</p>

<pre class="brush: js">const AsyncGeneratorFunction = Object.getPrototypeOf(async function*(){}).constructor;
const asyncGen = new AsyncGeneratorFunction('a', 'yield a * 2');
const asyncIterator = asyncGen(10);
console.log((await asyncIterator.next()).value); // 20
DerekNonGeneric marked this conversation as resolved.
Show resolved Hide resolved
</pre>

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

<table class="standard-table">
<thead>
<tr>
<th scope="col">Specification</th>
</tr>
</thead>
<tbody>
<tr>
<td>{{SpecName('ESDraft', '#sec-asyncgeneratorfunction-objects', 'AsyncGeneratorFunction')}}
</td>
</tr>
</tbody>
</table>

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

<p>{{Compat("javascript.builtins.AsyncGeneratorFunction")}}</p>

Copy link
Collaborator

Choose a reason for hiding this comment

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

Double blank line 👀

<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("Global_Objects/AsyncGenerator", "AsyncGenerator")}}</li>
<li>{{jsxref("Global_Objects/Generator", "Generator")}}</li>
<li>{{jsxref("Global_Objects/GeneratorFunction", "GeneratorFunction")}}</li>
<li>{{jsxref("Global_Objects/AsyncFunction", "AsyncFunction")}}</li>
<li><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Iterators_and_generators">Iterators and generators</a></li>
<li>{{jsxref("Functions_and_function_scope", "Functions and function scope", "", 1)}}</li>
</ul>