Created
March 17, 2019 17:11
-
-
Save pujansrt/5604b9893c091e3f8630a18d5f324d88 to your computer and use it in GitHub Desktop.
Async Await Best Pratices
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// The Async/Await section spreads some misinformation and bad practices. It explains that try/catch must be used whenever an await expression is used, but that is not the case. For example, this snippet: | |
function getGithubUser(username) { | |
return new Promise((resolve, reject) => { | |
fetch(`https://api.github.com/users/${username}`) | |
.then(response => { | |
const user = response.json(); | |
resolve(user); | |
}) | |
.catch(err => reject(err)); | |
}) | |
} | |
getGithubUser('mbeaudru') | |
.then(user => console.log(user)) | |
.catch(err => console.log(err)); | |
is the same as: | |
function getGithubUser(username) { | |
return fetch(`https://api.github.com/users/${username}`).then(response => response.json()); | |
} | |
getGithubUser('mbeaudru') | |
.then(user => console.log(user)) | |
.catch(err => console.log(err)); | |
// You don't need to wrap it in another Promise, fetch already returns a promise. | |
// This snippet is really bad, which I'll explain: | |
async function getGithubUser(username) { // promise + await keyword usage allowed | |
try { // We handle async function errors with try / catch | |
const response = await fetch(`https://api.github.com/users/${username}`); // Execution stops here until fetch promise is fulfilled. | |
const user = response.json(); | |
return user; // equivalent of resolving the getGithubUser promise with user value. | |
} catch (err) { | |
throw new Error(err); // equivalent of rejecting getGithubUser promise with err value. | |
} | |
} | |
getGithubUser('mbeaudru') | |
.then(user => console.log(user)) | |
.catch(err => console.log(err)); | |
// You don't need to have a try/catch block every time you have an await expression. You're already catching the error with .catch() on the last line. Any function that getGithubUser calls that throws, and any function the functions getGithubUser() calls that throws, and so on, will be caught by the last .catch(). It should be rewritten: | |
async function getGithubUser(username) { // promise + await keyword usage allowed | |
const response = await fetch(`https://api.github.com/users/${username}`); // Execution stops here until fetch promise is fulfilled. | |
const user = response.json(); | |
return user; // equivalent of resolving the getGithubUser promise with user value. | |
} | |
getGithubUser('mbeaudru') | |
.then(user => console.log(user)) | |
.catch(err => console.log(err)); | |
// Additionally, the throw new Error(err); is super bad because you lose the original error type and whatever custom stack trace implementation it has. For example: | |
class TlsHandshakeError extends Error {} | |
async function throws () { | |
throw new TlsHandshakeError("key mismatch"); | |
} | |
async function doSomething () { | |
try { | |
await throws() | |
} catch (e) { | |
throw new Error(e); | |
} | |
} | |
doSomething.catch(e => console.error(e)); | |
//The error written to console will be Error: Error: key mistmatch rather than TlsHandshakeError: key mismatch. | |
// The above could be: | |
class TlsHandshakeError extends Error {} | |
async function throws () { | |
throw new TlsHandshakeError("key mismatch"); | |
} | |
async function doSomething () { | |
await throws() | |
} | |
doSomething.catch(e => console.error(e)); // TlsHandshakeError: key mismatch | |
// The code below will catch the error and not crash the application: | |
async function throws () { | |
throw new Error("error"); | |
} | |
async function step1 () { | |
await throws(); | |
} | |
async function step2 () { | |
await step1(); | |
} | |
async function step3 () { | |
await step2(); | |
} | |
step3().catch((err) => { | |
// Error is caught here | |
console.log(err); // Error: error | |
}); | |
Same with the last snippet: | |
async function fetchPostById(postId) { | |
try { | |
const token = await fetch('token_url'); | |
const post = await fetch(`/posts/${postId}?token=${token}`); | |
const author = await fetch(`/users/${post.authorId}`); | |
post.author = author; | |
return post; | |
} catch(e) { | |
throw new Error(e); | |
} | |
} | |
fetchPostById('gzIrzeo64') | |
.then(post => console.log(post)) | |
.catch(err => console.log(err)); | |
should be: | |
async function fetchPostById(postId) { | |
const token = await fetch('token_url'); | |
const post = await fetch(`/posts/${postId}?token=${token}`); | |
const author = await fetch(`/users/${post.authorId}`) | |
post.author = author; | |
return post; | |
} | |
fetchPostById('gzIrzeo64') | |
.then(post => console.log(post)) | |
.catch(err => console.log(err)); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment