Skip to content

Commit 40440a1

Browse files
Svenskungankambeaudru
authored andcommitted
Clarifications in the async / await section (mbeaudru#69)
Minor bugfixes and clarifications
1 parent 70e19ba commit 40440a1

File tree

1 file changed

+25
-23
lines changed

1 file changed

+25
-23
lines changed

README.md

Lines changed: 25 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1267,45 +1267,45 @@ For classes understanding:
12671267

12681268
In addition to [Promises](#promises), there is a new syntax you might encounter to handle asynchronous code named *async / await*.
12691269

1270-
The purpose of async/await functions is to simplify the behavior of using promises synchronously and to perform some behavior on a group of Promises. Just as Promises are similar to structured callbacks, async/await is similar to combining generators and promises. ([Ref: MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function))
1270+
The purpose of async/await functions is to simplify the behavior of using promises synchronously and to perform some behavior on a group of Promises. Just as Promises are similar to structured callbacks, async/await is similar to combining generators and promises. Async functions *always* returns a Promise. ([Ref: MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function))
12711271

1272-
> **Note :** You must understand what are promises and how they work before trying to understand async / await since they rely on it.
1272+
> **Note :** You must understand what promises are and how they work before trying to understand async / await since they rely on it.
12731273
12741274
> **Note 2:** [*await* must be used in an *async* function](https://hackernoon.com/6-reasons-why-javascripts-async-await-blows-promises-away-tutorial-c7ec10518dd9#f3f0), which means that you can't use await in the top level of our code since that is not inside an async function.
12751275
12761276
#### Sample code
12771277

12781278
```js
12791279
async function getGithubUser(username) { // async keyword allows usage of await in the function and means function returns a promise
1280-
const response = await fetch(`https://api.github.com/users/${username}`); // "synchronously" waiting fetch promise to resolve before going to next line
1280+
const response = await fetch(`https://api.github.com/users/${username}`); // Execution is paused here until the Promise returned by fetch is resolved
12811281
return response.json();
12821282
}
12831283

12841284
getGithubUser('mbeaudru')
12851285
.then(user => console.log(user)) // logging user response - cannot use await syntax since this code isn't in async function
1286-
.catch(err => console.log(err)); // if an error is raised in our async function, we will catch it here
1286+
.catch(err => console.log(err)); // if an error is thrown in our async function, we will catch it here
12871287
```
12881288

12891289
#### Explanation with sample code
12901290

12911291
*Async / Await* is built on promises but they allow a more imperative style of code.
12921292

1293-
*async* operator turns a function into a *promise* in which you can use the *await* operator.
1293+
The *async* operator marks a function as asynchronous and will always return a *Promise*. You can use the *await* operator in an *async* function to pause execution on that line until the returned Promise from the expression either resolves or rejects.
12941294

12951295
```js
12961296
async function myFunc() {
12971297
// we can use await operator because this function is async
12981298
return "hello world";
12991299
}
13001300

1301-
myFunc().then(msg => console.log(msg)) // "hello world" -- myFunc is turned into a promise because of async operator
1301+
myFunc().then(msg => console.log(msg)) // "hello world" -- myFunc's return value is turned into a promise because of async operator
13021302
```
13031303

1304-
When the *return* statement of an async function is reached, the promise is fulfilled with the value returned. If an error is thrown inside an async function, the promise state will turn to *rejected*.
1304+
When the *return* statement of an async function is reached, the Promise is fulfilled with the value returned. If an error is thrown inside an async function, the Promise state will turn to *rejected*. If no value is returned from an async function, a Promise is still returned and resolves with no value when execution of the async function is complete.
13051305

1306-
*await* operator is used to wait for a *Promise* to be fulfilled and only can be used inside an *async* function body. When encountered, the code execution is paused until the promise is fulfilled.
1306+
*await* operator is used to wait for a *Promise* to be fulfilled and can only be used inside an *async* function body. When encountered, the code execution is paused until the promise is fulfilled.
13071307

1308-
> **Note :** *fetch* is a Promise that allows to do an AJAX request
1308+
> **Note :** *fetch* is a function that returns a Promise that allows to do an AJAX request
13091309
13101310
Let's see how we could fetch a github user with promises first:
13111311

@@ -1323,7 +1323,7 @@ Here's the *async / await* equivalent:
13231323

13241324
```js
13251325
async function getGithubUser(username) { // promise + await keyword usage allowed
1326-
const response = await fetch(`https://api.github.com/users/${username}`); // Execution stops here until fetch promise is fulfilled.
1326+
const response = await fetch(`https://api.github.com/users/${username}`); // Execution stops here until fetch promise is fulfilled
13271327
return response.json();
13281328
}
13291329

@@ -1336,11 +1336,13 @@ getGithubUser('mbeaudru')
13361336

13371337
For instance, if you need to get a token in order to be able to fetch a blog post on a database and then the author informations:
13381338

1339+
> **Note :** *await* expressions needs to be wrapped in parentheses to call its resolved value's methods and properties on the same line.
1340+
13391341
```js
13401342
async function fetchPostById(postId) {
1341-
const token = await fetch('token_url');
1342-
const post = await fetch(`/posts/${postId}?token=${token}`);
1343-
const author = await fetch(`/users/${post.authorId}`);
1343+
const token = (await fetch('token_url')).json().token;
1344+
const post = (await fetch(`/posts/${postId}?token=${token}`)).json();
1345+
const author = (await fetch(`/users/${post.authorId}`)).json();
13441346

13451347
post.author = author;
13461348
return post;
@@ -1353,41 +1355,41 @@ fetchPostById('gzIrzeo64')
13531355

13541356
##### Error handling
13551357

1356-
Unless we add *try / catch* blocks around *await* expressions, uncaught exceptions – regardless of whether they were raised in the body of your *async* function or while it’s suspended during *await* – will reject the promise returned by the *async* function. [(Ref: PonyFoo)](https://ponyfoo.com/articles/understanding-javascript-async-await#error-handling).
1358+
Unless we add *try / catch* blocks around *await* expressions, uncaught exceptions – regardless of whether they were thrown in the body of your *async* function or while it’s suspended during *await* – will reject the promise returned by the *async* function. Using the `throw` statement in an async function is the same as returning a Promise that rejects. [(Ref: PonyFoo)](https://ponyfoo.com/articles/understanding-javascript-async-await#error-handling).
13571359

13581360
> **Note :** Promises behave the same!
13591361
13601362
With promises, here is how you would handle the error chain:
13611363

13621364
```js
13631365
function getUser() { // This promise will be rejected!
1364-
return new Promise((res, rej) => rej("User not found !"))
1365-
};
1366+
return new Promise((res, rej) => rej("User not found !"));
1367+
}
13661368

13671369
function getAvatarByUsername(userId) {
1368-
return getUser(userId).then(user => res(user.avatar))
1370+
return getUser(userId).then(user => user.avatar);
13691371
}
13701372

13711373
function getUserAvatar(username) {
1372-
return getAvatarByUsername(username).then(avatar => res({ username, avatar }))
1374+
return getAvatarByUsername(username).then(avatar => ({ username, avatar }));
13731375
}
13741376

13751377
getUserAvatar('mbeaudru')
13761378
.then(res => console.log(res))
13771379
.catch(err => console.log(err)); // "User not found !"
13781380
```
13791381

1380-
With *async / await*:
1382+
The equivalent with *async / await*:
13811383

13821384
```js
1383-
function getUser() { // This promise will be rejected!
1384-
return new Promise((res, rej) => rej("User not found !"))
1385-
};
1385+
async function getUser() { // The returned promise will be rejected!
1386+
throw "User not found !";
1387+
}
13861388

13871389
async function getAvatarByUsername(userId) => {
13881390
const user = await getUser(userId);
13891391
return user.avatar;
1390-
};
1392+
}
13911393

13921394
async function getUserAvatar(username) {
13931395
var avatar = await getAvatarByUsername(username);

0 commit comments

Comments
 (0)