As a continuation of my PR for Telescope, I thought I should talk a bit about async/await and the old way of using return new Promise(). Here are a few examples of do's and don'ts:
// Async functions return promises, no need to add await
// DON"T DO
async function returnsPromise(){
return await promiseFunction();
}
// DO
async function returnsPromiseFixed(){
return promiseFunction();
}
//---------------------------------------------------------------------------
// Don't use await when function is not async
// DON"T DO
function noAsync(){
let promise = await promiseFunction();
}
// DO
async function noAsyncFixed(){
let promise = await promiseFunction();
}
//---------------------------------------------------------------------------
// Writing errors
async function f() {
await Promise.reject(New Error("Error"));
}
// SAME AS
async function f() {
throw new Error("Error");
}
//---------------------------------------------------------------------------
// Use try catch to wrap only code that can throw
// DON"T DO
async function tryCatch() {
try {
const fetchResult = await fetch();
const data = await fetchResult.json();
const t = blah();
} catch (error) {
logger.log(error);
throw new Error(error);
}
}
// DO
async function tryCatchFixed() {
try {
const fetchResult = await fetch();
const data = await fetchResult.json();
} catch (error) {
logger.log(error);
throw new Error(error);
}
}
const t = blah();
//---------------------------------------------------------------------------
// Use async/await. Don't use Promises
// DON"T DO
async function usePromise() {
new Promise(function(res, rej) {
if (isValidString) {
res(analysis);
} else {
res(textInfo);
}
if (isValidStrinng === undefined) {
rej(textInfo);
}
})
}
// DO
async function usePromiseFixed() {
const asyResult = await asyFunc()
}
// --------------------------------------------------------------------------
// Don't use async when it is not needed... Don't be overzealous with async/await
// For example the sentiment module we're using is not an async function
// DON"T DO
module.exports.run = async function(text) {
const sentiment = new Sentiment();
return Promise.resolve(sentiment.analyze(text));
};
// DO
module.exports.run = function(text) {
const sentiment = new Sentiment();
return sentiment.analyze(text);
};
// --------------------------------------------------------------------------
// Avoid making things too sequential
// DON"T DO
async function logInOrder(urls) {
for (const url of urls) {
const response = await fetch(url);
console.log(await response.text());
}
}
// DO
async function logInOrder(urls) {
// fetch all the URLs in parallel
const textPromises = urls.map(async url => {
const response = await fetch(url);
return response.text();
});
// log them in sequence
for (const textPromise of textPromises) {
console.log(await textPromise);
}
}
// --------------------------------------------------------------------------
// Examples
// refactor following function:
function loadJson(url) {
return fetch(url)
.then(response => {
if (response.status == 200) {
return response.json();
} else {
throw new Error(response.status);
}
})
}
// Solution:
function loadJson(url) {
let fetchResult = await fetch(url);
if (fetchResult.status == 200){
let json = await fetchResult.json();
return json;
}
throw new Error(fetchResult.status);
}
// refactor to use try/catch
function demoGithubUser() {
let name = prompt("Enter a name?", "iliakan");
return loadJson(`https://api.github.com/users/${name}`)
.then(user => {
alert(`Full name: ${user.name}.`);
return user;
})
.catch(err => {
if (err instanceof HttpError && err.response.status == 404) {
alert("No such user, please reenter.");
return demoGithubUser();
} else {
throw err;
}
});
}
demoGithubUser();
// Solution:
async function demoGithubUser() {
let user;
while(true){
let name = prompt("Enter a name?", "iliakan");
try {
user = await loadJson(`https://api.github.com/users/${name}`)
break;
} catch (err) {
if (err) {
alert("No such user, please reenter.");
return demoGithubUser();
} else {
throw err;
}
}
}
}
// Call async from non-async
async function wait() {
await new Promise(resolve => setTimeout(resolve, 1000));
return 10;
}
function f() {
// ...what to write here?
// we need to call async wait() and wait to get 10
// remember, we can't use "await"
}
// Solution:
function f() {
wait().then(result => alert(result));
}
No comments:
Post a Comment