As I’ve stated in a lot of other posts, I’m a big fan of async/await. I think it’s a pretty clean way to manage code your synchronous and asynchronous code.
I want to compare some of the bad that can be avoided with async/await.
// Yucky then usage async function getThePizza() { functionGettingFromMongo('someArguments').then((someData) => { // We want to use this data so we need to know that this promise completed doSomeWorkWithAPromise().then((moreData) => { const somethingCool = someData + moreData;insertToMongoNow(somethingCool).then((response) => {
console.log(‘success!’, response);
}).catch((e) => {
console.log(‘some error happened’, e);
});
});});
}
So this is a function where we are entering callback hell. While .then()
isn’t a callback function, codewise it reads the exact same. It’s a bunch of nested functions that get deeper and deeper and make code less and less readable.
// So good.
async function getThePizza() {
const someData = await functionGettingFromMongo(‘someArguments’);
const moreData = await doSomeWorkWithAPromise();const somethingCool = someData + moreData;
try {
const response = insertToMongoNow(somethingCool );
console.log(‘success!’, response);
}
catch(e) {
console.log(‘some error happened’, e);
}
}
It’s a lot more readable. At the least it’s not getting more and more indented. I had been using async/await exclusively since I discovered it so much so that I started thinking of .then()
as bad and kind of forgot that the beauty of programming is that almost everything is situational.
.then()
isn’t so badWhen I’m trying to scrape a lot of pages at once I don’t want to be blocked. I don’t use await but instead push the promises into an array and use Promise.all
. That will ensure that I know when everything completes so I can close my db connection or puppeteer browser. Like this:
async function getThePizza() {
const promises: any[] = [];
for (let url of lotsAndLotsOfUrls) {
promises.push(functionForHandlingTheUrl(url));
}await Promise.all(promises);
await closeMyDbConnectionOrPuppeteerOrSomething();
}
This works fine. Except for when I want to do something with the specific url after functionForHandlingTheUrl
finishes with it. Now what? Using await
looks like this:
async function getThePizza() {
for (let url of lotsAndLotsOfUrls) {
const something = await functionForHandlingTheUrl(url);
await dbWorkOrSomething(something);
}await closeMyDbConnectionOrPuppeteerOrSomething();
}
Very readable but much slower. I’m no longer taking advantage of any concurrency around I/O threads. So what’s the better alternative? This worked GREAT:
async function getThePizza() {
const promises: any[] = [];
for (let url of lotsAndLotsOfUrls) {
promises.push(functionForHandlingTheUrl(url).then(something => {
// This parts only happens when functionForHandlingTheUrl completes and doesn’t block the rest
await dbWorkOrSomething(something);
}));}
await Promise.all(promises);
await closeMyDbConnectionOrPuppeteerOrSomething();
}
Using .then()
here makes it so I have one nested function, it’s true, but we are able to do stuff when only that specific iteration is ready. It doesn’t block the rest of the looping so I am still lightning fast. And I am happy.
Thanks for reading ❤
If you liked this post, please do share/like it with all of your programming buddies!
Follow us on Facebook | Twitter
☞ The Complete JavaScript Course 2019: Build Real Projects!
☞ Vue JS 2 - The Complete Guide (incl. Vue Router & Vuex)
☞ JavaScript Bootcamp - Build Real World Applications
☞ JavaScript Programming Tutorial - Full JavaScript Course for Beginners
☞ New ES2019 Features Every JavaScript Developer Should Know
☞ Best JavaScript Frameworks, Libraries and Tools to Use in 2019
☞ React vs Angular vs Vue.js by Example
#javascript #web-development