Skip to content
This repository was archived by the owner on Aug 10, 2022. It is now read-only.

Commit 52f106f

Browse files
committed
Adding description. Wrapping text.
1 parent 7432545 commit 52f106f

File tree

1 file changed

+80
-27
lines changed

1 file changed

+80
-27
lines changed

src/content/en/fundamentals/getting-started/primers/async-functions.md

Lines changed: 80 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
project_path: /web/_project.yaml
22
book_path: /web/fundamentals/_book.yaml
3-
description: TODO
3+
description: Async functions allow you to write promise-based code as if it were synchronous
44

55
{# wf_published_on: 2016-10-07 #}
66
{# wf_updated_on: 2016-10-07 #}
@@ -9,7 +9,10 @@ description: TODO
99

1010
{% include "web/_shared/contributors/jakearchibald.html" %}
1111

12-
Async functions are enabled by default in Chrome 55 and they're quite frankly marvelous. They allow you to write promise-based code as if it were synchronous, but without blocking the main thread. They make your asynchronous code less "clever" and more readable.
12+
Async functions are enabled by default in Chrome 55 and they're quite frankly
13+
marvelous. They allow you to write promise-based code as if it were synchronous,
14+
but without blocking the main thread. They make your asynchronous code less
15+
"clever" and more readable.
1316

1417
Async functions look like this:
1518

@@ -22,11 +25,16 @@ Async functions look like this:
2225
}
2326
}
2427

25-
If you use the `async` keyword before a function definition, you can then use `await` within the function. When you `await` a promise, the function is paused until the promise settles. If the promise fulfills, you get the value back. If the promise rejects, the rejected value is thrown.
28+
If you use the `async` keyword before a function definition, you can then use
29+
`await` within the function. When you `await` a promise, the function is paused
30+
until the promise settles. If the promise fulfills, you get the value back. If
31+
the promise rejects, the rejected value is thrown.
2632

27-
Note: If you're unfamiliar with promises & promise terminology, check out [our promises guide](/web/fundamentals/getting-started/primers/promises).
33+
Note: If you're unfamiliar with promises & promise terminology, check out [our
34+
promises guide](/web/fundamentals/getting-started/primers/promises).
2835

29-
Calling an async function returns a promise for whatever the function returns or throws. So with:
36+
Calling an async function returns a promise for whatever the function returns or
37+
throws. So with:
3038

3139
// wait ms milliseconds
3240
function wait(ms) {
@@ -47,11 +55,14 @@ Calling an async function returns a promise for whatever the function returns or
4755

4856
…calling `foo()` returns a promise that *rejects* with `Error('bar')`.
4957

50-
Note: You can only use `await` directly inside an async function. There's some discussion to allow top-level `await` in modules, but it's [somewhat controversial](https://gist.github.com/Rich-Harris/0b6f317657f5167663b493c722647221).
58+
Note: You can only use `await` directly inside an async function. There's some
59+
discussion to allow top-level `await` in modules, but it's [somewhat
60+
controversial](https://gist.github.com/Rich-Harris/0b6f317657f5167663b493c722647221).
5161

5262
## Example: Logging a fetch
5363

54-
Say we wanted to fetch a URL and log the response as text. Here's how it looks using promises:
64+
Say we wanted to fetch a URL and log the response as text. Here's how it looks
65+
using promises:
5566

5667
function logFetch(url) {
5768
return fetch(url)
@@ -75,11 +86,13 @@ And here's the same thing using async functions:
7586
}
7687
}
7788

78-
It's the same number of lines, but all the callbacks are gone. This makes it way easier to read, especially for those less familiar with promises.
89+
It's the same number of lines, but all the callbacks are gone. This makes it way
90+
easier to read, especially for those less familiar with promises.
7991

8092
## Other async function syntax
8193

82-
We've seen `async function() {}` already, but the `async` keyword can be used with other function syntax:
94+
We've seen `async function() {}` already, but the `async` keyword can be used
95+
with other function syntax:
8396

8497
### Arrow functions
8598

@@ -89,7 +102,9 @@ We've seen `async function() {}` already, but the `async` keyword can be used wi
89102
return response.json();
90103
});
91104

92-
Note: `array.map(func)` doesn't care that I gave it an async function, it just sees it as a function that returns a promise. It won't wait for the first function to complete before calling the second.
105+
Note: `array.map(func)` doesn't care that I gave it an async function, it just
106+
sees it as a function that returns a promise. It won't wait for the first
107+
function to complete before calling the second.
93108

94109
### Object methods
95110

@@ -122,7 +137,8 @@ Note: Class constructors cannot be async.
122137

123138
## Example: Streaming a response
124139

125-
The benefit of async functions increases in more complex examples. Say we wanted to stream a response while logging out the chunks and returning the final size.
140+
The benefit of async functions increases in more complex examples. Say we wanted
141+
to stream a response while logging out the chunks and returning the final size.
126142

127143
Note: The phrase "logging out the chunks" made me sick in my mouth.
128144

@@ -145,7 +161,11 @@ Here it is with promises:
145161
});
146162
}
147163

148-
Check me out, Jake "wielder of promises" Archibald. See how I'm calling `processResult` inside itself to set up an asynchronous loop? Writing that made me feel *very smart*. But like most "smart" code, you have to stare at it for ages to figure out what it's doing, like one of those magic-eye pictures from the 90's.
164+
Check me out, Jake "wielder of promises" Archibald. See how I'm calling
165+
`processResult` inside itself to set up an asynchronous loop? Writing that made
166+
me feel *very smart*. But like most "smart" code, you have to stare at it for
167+
ages to figure out what it's doing, like one of those magic-eye pictures from
168+
the 90's.
149169

150170
Let's try that again with async functions:
151171

@@ -164,13 +184,22 @@ Let's try that again with async functions:
164184
return total;
165185
}
166186

167-
All the "smart" is gone. The asynchronous loop that made me feel so smug is replaced with a trusty, boring, while-loop. Much better. In future, we'll get [async iterators](https://github.com/tc39/proposal-async-iteration){: .external}, which would [replace the above `while` loop](https://gist.github.com/jakearchibald/0b37865637daf884943cf88c2cba1376){: .external}.
187+
All the "smart" is gone. The asynchronous loop that made me feel so smug is
188+
replaced with a trusty, boring, while-loop. Much better. In future, we'll get
189+
[async iterators](https://github.com/tc39/proposal-async-iteration){:
190+
.external}, which would [replace the above `while`
191+
loop](https://gist.github.com/jakearchibald/0b37865637daf884943cf88c2cba1376){:
192+
.external}.
168193

169-
Note: I'm sort-of in love with streams. If you're unfamiliar with streaming, [check out my guide](https://jakearchibald.com/2016/streams-ftw/#streams-the-fetch-api){: .external}.
194+
Note: I'm sort-of in love with streams. If you're unfamiliar with streaming,
195+
[check out my
196+
guide](https://jakearchibald.com/2016/streams-ftw/#streams-the-fetch-api){:
197+
.external}.
170198

171199
## Example: Avoid going too sequential
172200

173-
Say we wanted to fetch a series URLs and log them as soon as possible, in the correct order.
201+
Say we wanted to fetch a series URLs and log them as soon as possible, in the
202+
correct order.
174203

175204
*Deep breath* - here's how that looks with promises:
176205

@@ -187,9 +216,11 @@ Say we wanted to fetch a series URLs and log them as soon as possible, in the co
187216
}, Promise.resolve());
188217
}
189218

190-
Yeah, that's right, I'm using `reduce` to chain a sequence of promises. I'm *so smart*. But this is a bit of *so smart* coding we're better off without.
219+
Yeah, that's right, I'm using `reduce` to chain a sequence of promises. I'm *so
220+
smart*. But this is a bit of *so smart* coding we're better off without.
191221

192-
However, when converting the above to an async function, it's tempting to go *too sequential*:
222+
However, when converting the above to an async function, it's tempting to go
223+
*too sequential*:
193224

194225
<span class="compare-worse">Not recommended</span> - too sequential
195226

@@ -200,7 +231,9 @@ However, when converting the above to an async function, it's tempting to go *to
200231
}
201232
}
202233

203-
Looks much neater, but my second fetch doesn't begin until my first fetch has been fully read, and so on. This is much slower than the promises example that performs the fetches in parallel. Thankfully there's an ideal middle-ground:
234+
Looks much neater, but my second fetch doesn't begin until my first fetch has
235+
been fully read, and so on. This is much slower than the promises example that
236+
performs the fetches in parallel. Thankfully there's an ideal middle-ground:
204237

205238
<span class="compare-better">Recommended</span> - nice and parallel
206239

@@ -217,42 +250,62 @@ Looks much neater, but my second fetch doesn't begin until my first fetch has be
217250
}
218251
}
219252

220-
In this example, the URLs are fetched and read in parallel, but the "smart" `reduce` bit is replaced with a standard, boring, readable for-loop.
253+
In this example, the URLs are fetched and read in parallel, but the "smart"
254+
`reduce` bit is replaced with a standard, boring, readable for-loop.
221255

222256
## Browser support & workarounds
223257

224-
At time of writing, async functions are enabled by default in Chrome 55, but they're being developed in all the main browsers:
258+
At time of writing, async functions are enabled by default in Chrome 55, but
259+
they're being developed in all the main browsers:
225260

226261
* Edge - [In build 14342+ behind a flag](https://developer.microsoft.com/en-us/microsoft-edge/platform/status/asyncfunctions/)
227262
* Firefox - [active development](https://bugzilla.mozilla.org/show_bug.cgi?id=1185106)
228263
* Safari - [active development](https://bugs.webkit.org/show_bug.cgi?id=156147)
229264

230265
### Workaround - Generators
231266

232-
If you're targeting browsers that support generators (which includes [the latest version of every major browser](http://kangax.github.io/compat-table/es6/#test-generators){: .external}) you can sort-of polyfill async functions.
267+
If you're targeting browsers that support generators (which includes [the latest
268+
version of every major
269+
browser](http://kangax.github.io/compat-table/es6/#test-generators){:
270+
.external}) you can sort-of polyfill async functions.
233271

234-
[Babel](https://babeljs.io/){: .external} will do this for you, [here's an example via the Babel REPL](https://goo.gl/0Cg1Sq){: .external} - note how similar the transpiled code is. This transformation is part of [Babel's stage 3 preset](http://babeljs.io/docs/plugins/preset-stage-3/){: .external}.
272+
[Babel](https://babeljs.io/){: .external} will do this for you, [here's an
273+
example via the Babel REPL](https://goo.gl/0Cg1Sq){: .external} - note how
274+
similar the transpiled code is. This transformation is part of [Babel's stage 3
275+
preset](http://babeljs.io/docs/plugins/preset-stage-3/){: .external}.
235276

236277
Note: Babel REPL is fun to say. Try it.
237278

238-
I recommend the transpiling approach, because you can just turn it off once your target browsers support async functions, but if you *really* don't want to use a transpiler, you can take [Babel's polyfill](https://gist.github.com/jakearchibald/edbc78f73f7df4f7f3182b3c7e522d25){: .external} and use it yourself. Instead of:
279+
I recommend the transpiling approach, because you can just turn it off once your
280+
target browsers support async functions, but if you *really* don't want to use a
281+
transpiler, you can take [Babel's
282+
polyfill](https://gist.github.com/jakearchibald/edbc78f73f7df4f7f3182b3c7e522d25){:
283+
.external} and use it yourself. Instead of:
239284

240285
async function slowEcho(val) {
241286
await wait(1000);
242287
return val;
243288
}
244289

245-
…you'd include [the polyfill](https://gist.github.com/jakearchibald/edbc78f73f7df4f7f3182b3c7e522d25){: .external} and write:
290+
…you'd include [the
291+
polyfill](https://gist.github.com/jakearchibald/edbc78f73f7df4f7f3182b3c7e522d25){:
292+
.external} and write:
246293

247294
const slowEcho = createAsyncFunction(function*(val) {
248295
yield wait(1000);
249296
return val;
250297
});
251298

252-
Note that you have to pass a generator (`function*`) to `createAsyncFunction`, and use `yield` instead of `await`. Other than that it works the same.
299+
Note that you have to pass a generator (`function*`) to `createAsyncFunction`,
300+
and use `yield` instead of `await`. Other than that it works the same.
253301

254302
### Workaround - regenerator
255303

256-
If you're targeting older browsers, Babel can also transpile generators, allowing you to use async functions all the way down to IE8. To do this you need [Babel's stage 3 preset](http://babeljs.io/docs/plugins/preset-stage-3/){: .external} *and* the [ES2015 preset](http://babeljs.io/docs/plugins/preset-es2015/){: .external}.
304+
If you're targeting older browsers, Babel can also transpile generators,
305+
allowing you to use async functions all the way down to IE8. To do this you need
306+
[Babel's stage 3 preset](http://babeljs.io/docs/plugins/preset-stage-3/){:
307+
.external} *and* the [ES2015
308+
preset](http://babeljs.io/docs/plugins/preset-es2015/){: .external}.
257309

258-
The [output is not as pretty](https://goo.gl/jlXboV), so watch out for code-bloat.
310+
The [output is not as pretty](https://goo.gl/jlXboV), so watch out for
311+
code-bloat.

0 commit comments

Comments
 (0)