{"id":378,"date":"2018-06-14T22:49:41","date_gmt":"2018-06-14T22:49:41","guid":{"rendered":"https:\/\/blog.hassler.ec\/wp\/?p=378"},"modified":"2018-06-14T22:49:41","modified_gmt":"2018-06-14T22:49:41","slug":"javascript-async-await-the-good-part-pitfalls-and-how-to-use","status":"publish","type":"post","link":"https:\/\/blog.hassler.ec\/wp\/2018\/06\/14\/javascript-async-await-the-good-part-pitfalls-and-how-to-use\/","title":{"rendered":"JavaScript async\/await: The Good Part, Pitfalls and How to\u00a0Use"},"content":{"rendered":"<section class=\"section section--body section--first\">\n<div class=\"section-content\">\n<div class=\"section-inner sectionLayout--insetColumn\">\n<figure id=\"dcc8\" class=\"graf graf--figure graf-after--h3\">\n<div class=\"aspectRatioPlaceholder is-locked\">\n<div class=\"aspectRatioPlaceholder-fill\"><\/div>\n<div class=\"progressiveMedia js-progressiveMedia graf-image is-canvasLoaded is-imageLoaded\" data-image-id=\"1*dNtmhr-N1J1L__E2rEj5jg.png\" data-width=\"800\" data-height=\"450\" data-action=\"zoom\" data-action-value=\"1*dNtmhr-N1J1L__E2rEj5jg.png\" data-scroll=\"native\"><canvas class=\"progressiveMedia-canvas js-progressiveMedia-canvas\" width=\"75\" height=\"41\"><\/canvas><img decoding=\"async\" class=\"progressiveMedia-image js-progressiveMedia-image\" src=\"https:\/\/cdn-images-1.medium.com\/max\/1600\/1*dNtmhr-N1J1L__E2rEj5jg.png\" data-src=\"https:\/\/cdn-images-1.medium.com\/max\/1600\/1*dNtmhr-N1J1L__E2rEj5jg.png\" \/><\/div>\n<\/div>\n<\/figure>\n<p id=\"d2ec\" class=\"graf graf--p graf-after--figure\">The\u00a0<code class=\"markup--code markup--p-code\">async\/await<\/code>\u00a0introduced by ES7 is a fantastic improvement in asynchronous programming with JavaScript. It provided an option of using synchronous style code to access resoruces asynchronously, without blocking the main thread. However it is a bit tricky to use it well. In this article we will explore async\/await from different perspectives, and will show how to use them correctly and effectively.<\/p>\n<h3 id=\"6bba\" class=\"graf graf--h3 graf-after--p\">The good part in async\/await<\/h3>\n<p id=\"147f\" class=\"graf graf--p graf-after--h3\">The most important benefit\u00a0<code class=\"markup--code markup--p-code\">async\/await<\/code>\u00a0brought to us is the synchronous programming style. Let\u2019s see an example.<\/p>\n<pre id=\"9e07\" class=\"graf graf--pre graf-after--p\">\/\/ async\/await\r\nasync getBooksByAuthorWithAwait(authorId) {\r\n  const books = await bookModel.fetchAll();\r\n  return books.filter(b =&gt; b.authorId === authorId);\r\n}<\/pre>\n<pre id=\"bfd1\" class=\"graf graf--pre graf-after--pre\">\/\/ promise\r\ngetBooksByAuthorWithPromise(authorId) {\r\n  return bookModel.fetchAll()\r\n    .then(books =&gt; books.filter(b =&gt; b.authorId === authorId));\r\n}<\/pre>\n<p id=\"df2e\" class=\"graf graf--p graf-after--pre\">It is obvious that the\u00a0<code class=\"markup--code markup--p-code\">async\/await<\/code>version is way easier understanding than the promise version. If you ignore the\u00a0<code class=\"markup--code markup--p-code\">await<\/code>\u00a0keyword, the code just looks like any other synchronous languages such as Python.<\/p>\n<p id=\"af6e\" class=\"graf graf--p graf-after--p\">And the sweet spot is not only readability.\u00a0<code class=\"markup--code markup--p-code\">async\/await<\/code>\u00a0has native browser support. As of today, all the mainstream browsers have full support to async functions.<\/p>\n<figure id=\"a87f\" class=\"graf graf--figure graf-after--p\">\n<div class=\"aspectRatioPlaceholder is-locked\">\n<div class=\"aspectRatioPlaceholder-fill\"><\/div>\n<div class=\"progressiveMedia js-progressiveMedia graf-image is-canvasLoaded is-imageLoaded\" data-image-id=\"1*c6bYahABUDpGgMpJVak4Ag.png\" data-width=\"1093\" data-height=\"454\" data-action=\"zoom\" data-action-value=\"1*c6bYahABUDpGgMpJVak4Ag.png\" data-scroll=\"native\"><canvas class=\"progressiveMedia-canvas js-progressiveMedia-canvas\" width=\"75\" height=\"30\"><\/canvas><img decoding=\"async\" class=\"progressiveMedia-image js-progressiveMedia-image\" src=\"https:\/\/cdn-images-1.medium.com\/max\/1600\/1*c6bYahABUDpGgMpJVak4Ag.png\" data-src=\"https:\/\/cdn-images-1.medium.com\/max\/1600\/1*c6bYahABUDpGgMpJVak4Ag.png\" \/><\/div>\n<\/div><figcaption class=\"imageCaption\">All mainstream browsers support Async functions. (Source:\u00a0<a class=\"markup--anchor markup--figure-anchor\" href=\"https:\/\/caniuse.com\/\" target=\"_blank\" rel=\"nofollow noopener noopener noopener\" data-href=\"https:\/\/caniuse.com\/\">https:\/\/caniuse.com\/<\/a>)<\/figcaption><\/figure>\n<p id=\"d58e\" class=\"graf graf--p graf-after--figure\">Native support means you don\u2019t have to\u00a0<a class=\"markup--anchor markup--p-anchor\" href=\"https:\/\/babeljs.io\/docs\/plugins\/transform-async-to-generator\/\" target=\"_blank\" rel=\"noopener\" data-href=\"https:\/\/babeljs.io\/docs\/plugins\/transform-async-to-generator\/\">transpile<\/a>\u00a0the code. More importantly, it facilitates debugging. When you set a breakpoint at the function entry point and step over the\u00a0<code class=\"markup--code markup--p-code\">await<\/code>\u00a0line, you will see the debugger halt for a short while while\u00a0<code class=\"markup--code markup--p-code\">bookModel.fetchAll()<\/code>\u00a0doing its job, then it moves to the next\u00a0<code class=\"markup--code markup--p-code\">.filter<\/code>line! This is much easier than the promise case, in which you have to setup another breakpoint on the\u00a0<code class=\"markup--code markup--p-code\">.filter<\/code>\u00a0line.<\/p>\n<figure id=\"94b1\" class=\"graf graf--figure graf-after--p\">\n<div class=\"aspectRatioPlaceholder is-locked\">\n<div class=\"aspectRatioPlaceholder-fill\"><\/div>\n<div class=\"progressiveMedia js-progressiveMedia graf-image is-canvasLoaded is-imageLoaded\" data-image-id=\"1*bATX6Yjrsowx3AElqVSCVA.gif\" data-width=\"901\" data-height=\"469\" data-action=\"zoom\" data-action-value=\"1*bATX6Yjrsowx3AElqVSCVA.gif\" data-scroll=\"native\"><canvas class=\"progressiveMedia-canvas js-progressiveMedia-canvas\" width=\"75\" height=\"38\"><\/canvas><img decoding=\"async\" class=\"progressiveMedia-image js-progressiveMedia-image\" src=\"https:\/\/cdn-images-1.medium.com\/max\/1600\/1*bATX6Yjrsowx3AElqVSCVA.gif\" data-src=\"https:\/\/cdn-images-1.medium.com\/max\/1600\/1*bATX6Yjrsowx3AElqVSCVA.gif\" \/><\/div>\n<\/div><figcaption class=\"imageCaption\">Debugging async function. Debugger will wait at the await line and move to the next on resolved.<\/figcaption><\/figure>\n<p id=\"a338\" class=\"graf graf--p graf-after--figure\">Another less obvious benefit is the\u00a0<code class=\"markup--code markup--p-code\">async<\/code>\u00a0keyword. It declares that the\u00a0<code class=\"markup--code markup--p-code\">getBooksByAuthorWithAwait()<\/code>\u00a0function return value is guaranteed to be a promise, so that callers can call\u00a0<code class=\"markup--code markup--p-code\">getBooksByAuthorWithAwait().then(...)<\/code>\u00a0or\u00a0<code class=\"markup--code markup--p-code\">await getBooksByAuthorWithAwait()<\/code>\u00a0safely. Think about this case (bad practice!):<\/p>\n<pre id=\"9609\" class=\"graf graf--pre graf-after--p\">getBooksByAuthorWithPromise(authorId) {\r\n  if (!authorId) {\r\n    return null;\r\n  }\r\n  return bookModel.fetchAll()\r\n    .then(books =&gt; books.filter(b =&gt; b.authorId === authorId));\r\n  }\r\n}<\/pre>\n<p id=\"6a4c\" class=\"graf graf--p graf-after--pre\">In above code,\u00a0<code class=\"markup--code markup--p-code\">getBooksByAuthorWithPromise<\/code>\u00a0may return a promise (normal case) or a\u00a0<code class=\"markup--code markup--p-code\">null<\/code>\u00a0value (exceptional case), in which case caller cannot call\u00a0<code class=\"markup--code markup--p-code\">.then()<\/code>\u00a0safely. With\u00a0<code class=\"markup--code markup--p-code\">async<\/code>\u00a0declaration, it becomes impossible for this kind of code.<\/p>\n<h3 id=\"a392\" class=\"graf graf--h3 graf-after--p\">Async\/await Could Be Misleading<\/h3>\n<p id=\"adab\" class=\"graf graf--p graf-after--h3\">Some articles compare async\/await with Promise and claim it is the next generation in the evolution of JavaScript asynchronous programming, which I respectfully disagree. Async\/await IS an improvement, but it is no more than a syntactic sugar, which will not change our programming style completely.<\/p>\n<p id=\"3824\" class=\"graf graf--p graf-after--p\"><span class=\"markup--quote markup--p-quote is-other\" data-creator-ids=\"anon\">Essentially, async functions are still promises. You have to understand promises before you can use async functions correctly, and even worse, most of the time you need to use promises along with async functions.<\/span><\/p>\n<p id=\"9cab\" class=\"graf graf--p graf-after--p\">Consider the\u00a0<code class=\"markup--code markup--p-code\">getBooksByAuthorWithAwait()<\/code>\u00a0and\u00a0<code class=\"markup--code markup--p-code\">getBooksByAuthorWithPromises()<\/code>\u00a0functions in above example. Note that they are not only identical functionally, they also have exactly the same interface!<\/p>\n<p id=\"ff3b\" class=\"graf graf--p graf-after--p\">This means\u00a0<code class=\"markup--code markup--p-code\">getBooksByAuthorWithAwait()<\/code>\u00a0will return a promise if you call it directly.<\/p>\n<p id=\"40c2\" class=\"graf graf--p graf-after--p\">Well, this is not necessarily a bad thing. Only the name\u00a0<code class=\"markup--code markup--p-code\">await<\/code>\u00a0gives people a feeling that \u201cOh great this can convert asynchronous functions to synchronous functions\u201d which is actually wrong.<\/p>\n<h3 id=\"571d\" class=\"graf graf--h3 graf-after--p\">Async\/await Pitfalls<\/h3>\n<p id=\"a3d5\" class=\"graf graf--p graf-after--h3\">So what mistakes may be made when using\u00a0<code class=\"markup--code markup--p-code\">async\/await<\/code>? Here are some common ones.<\/p>\n<h4 id=\"2e52\" class=\"graf graf--h4 graf-after--p\">Too Sequential<\/h4>\n<p id=\"76be\" class=\"graf graf--p graf-after--h4\">Although\u00a0<code class=\"markup--code markup--p-code\">await<\/code>\u00a0can make your code look like synchronous, keep in mind that they are still asynchronous and care must be taken to avoid being too sequential.<\/p>\n<pre id=\"e5bb\" class=\"graf graf--pre graf-after--p\">async getBooksAndAuthor(authorId) {\r\n  const books = await bookModel.fetchAll();\r\n  const author = await authorModel.fetch(authorId);\r\n  return {\r\n    author,\r\n    books: books.filter(book =&gt; book.authorId === authorId),\r\n  };\r\n}<\/pre>\n<p id=\"f736\" class=\"graf graf--p graf-after--pre\">This code looks logically correct. However this is wrong.<\/p>\n<ol class=\"postList\">\n<li id=\"93fd\" class=\"graf graf--li graf-after--p\"><code class=\"markup--code markup--li-code\">await bookModel.fetchAll()<\/code>\u00a0will wait until\u00a0<code class=\"markup--code markup--li-code\">fetchAll()<\/code>\u00a0returns.<\/li>\n<li id=\"7d64\" class=\"graf graf--li graf-after--li\">Then\u00a0<code class=\"markup--code markup--li-code\">await authorModel.fetch(authorId)<\/code>\u00a0will be called.<\/li>\n<\/ol>\n<p id=\"d21d\" class=\"graf graf--p graf-after--li\">Notice that\u00a0<code class=\"markup--code markup--p-code\">authorModel.fetch(authorId)<\/code>\u00a0does not depend on the result of\u00a0<code class=\"markup--code markup--p-code\">bookModel.fetchAll()<\/code>\u00a0and in fact they can be called in parallel! However by using\u00a0<code class=\"markup--code markup--p-code\">await<\/code>\u00a0here these two calls become sequential and the total execution time will be much longer than the parallel version.<\/p>\n<p id=\"e5ae\" class=\"graf graf--p graf-after--p\">Here is the correct way:<\/p>\n<pre id=\"4524\" class=\"graf graf--pre graf-after--p\">async getBooksAndAuthor(authorId) {\r\n  const bookPromise = bookModel.fetchAll();\r\n  const authorPromise = authorModel.fetch(authorId);\r\n  const book = await bookPromise;\r\n  const author = await authorPromise;\r\n  return {\r\n    author,\r\n    books: books.filter(book =&gt; book.authorId === authorId),\r\n  };\r\n}<\/pre>\n<p id=\"b700\" class=\"graf graf--p graf-after--pre\">Or even worse, if you want to fetch a list of items one by one, you have to rely on promises:<\/p>\n<pre id=\"5948\" class=\"graf graf--pre graf-after--p\">async getAuthors(authorIds) {\r\n  \/\/ WRONG, this will cause sequential calls\r\n  \/\/ const authors = _.map(\r\n  \/\/   authorIds,\r\n  \/\/   id =&gt; await authorModel.fetch(id));<\/pre>\n<pre id=\"7cf0\" class=\"graf graf--pre graf-after--pre\">\/\/ CORRECT\r\n  const promises = _.map(authorIds, id =&gt; authorModel.fetch(id));\r\n  const authors = await Promise.all(promises);\r\n}<\/pre>\n<p id=\"d70f\" class=\"graf graf--p graf-after--pre\">In short, you still need to think about the workflows asynchronously, then try to write code synchronously with\u00a0<code class=\"markup--code markup--p-code\">await<\/code>. In complicated workflow it might be easier to use promises directly.<\/p>\n<h3 id=\"e9ad\" class=\"graf graf--h3 graf-after--p\">Error Handling<\/h3>\n<p id=\"cddc\" class=\"graf graf--p graf-after--h3\">With promises, an async function have two possible return values: resolved value, and rejected value. And we can use\u00a0<code class=\"markup--code markup--p-code\">.then()<\/code>\u00a0for normal case and\u00a0<code class=\"markup--code markup--p-code\">.catch()<\/code>\u00a0for exceptional case. However with\u00a0<code class=\"markup--code markup--p-code\">async\/await<\/code>\u00a0error handling could be tricky.<\/p>\n<h4 id=\"35c7\" class=\"graf graf--h4 graf-after--p\">try\u2026catch<\/h4>\n<p id=\"3f32\" class=\"graf graf--p graf-after--h4\">The most standard (and my recommended) way is to use\u00a0<code class=\"markup--code markup--p-code\">try...catch<\/code>statement. When\u00a0<code class=\"markup--code markup--p-code\">await<\/code>\u00a0a call, any rejected value will be thrown as an exception. Here is an example:<\/p>\n<pre id=\"8ee7\" class=\"graf graf--pre graf-after--p\">class BookModel {\r\n  fetchAll() {\r\n    return new Promise((resolve, reject) =&gt; {\r\n      window.setTimeout(() =&gt; { reject({'error': 400}) }, 1000);\r\n    });\r\n  }\r\n}<\/pre>\n<pre id=\"1433\" class=\"graf graf--pre graf-after--pre\">\/\/ async\/await\r\nasync getBooksByAuthorWithAwait(authorId) {\r\ntry {\r\n  const books = await bookModel.fetchAll();\r\n} catch (error) {\r\n  console.log(error);    \/\/ { \"error\": 400 }\r\n}<\/pre>\n<p id=\"180d\" class=\"graf graf--p graf-after--pre\">The\u00a0<code class=\"markup--code markup--p-code\">catch<\/code>ed error is exactly the rejected value. After we caught the exception, we have several ways to deal with it:<\/p>\n<ul class=\"postList\">\n<li id=\"e5b1\" class=\"graf graf--li graf-after--p\">Handle the exception, and return a normal value. (Not using any\u00a0<code class=\"markup--code markup--li-code\">return<\/code>statement in the\u00a0<code class=\"markup--code markup--li-code\">catch<\/code>\u00a0block is equivalent to using\u00a0<code class=\"markup--code markup--li-code\">return undefined;<\/code>and is a normal value as well.)<\/li>\n<li id=\"0846\" class=\"graf graf--li graf-after--li\">Throw it, if you want the caller to handle it. You can either throw the plain error object directly like\u00a0<code class=\"markup--code markup--li-code\">throw error;<\/code>, which allows you to use this\u00a0<code class=\"markup--code markup--li-code\">async getBooksByAuthorWithAwait()\u00a0<\/code>function in a promise chain (i.e. you can still call it like\u00a0<code class=\"markup--code markup--li-code\">getBooksByAuthorWithAwait().then(...).catch(error =&gt;\u00a0...)<\/code>); Or you can wrap the error with\u00a0<code class=\"markup--code markup--li-code\">Error<\/code>\u00a0object, like\u00a0<code class=\"markup--code markup--li-code\">throw new Error(error)<\/code>\u00a0, which will give the full stack trace when this error is displayed in the console.<\/li>\n<li id=\"397c\" class=\"graf graf--li graf-after--li\">Reject it, like\u00a0<code class=\"markup--code markup--li-code\">return Promise.reject(error)<\/code>\u00a0. This is equivalent to\u00a0<code class=\"markup--code markup--li-code\">throw error<\/code>\u00a0so it is not recommended.<\/li>\n<\/ul>\n<p id=\"64a1\" class=\"graf graf--p graf-after--li\">The benefits of using\u00a0<code class=\"markup--code markup--p-code\">try...catch<\/code>\u00a0are:<\/p>\n<ul class=\"postList\">\n<li id=\"f1c0\" class=\"graf graf--li graf-after--p\">Simple, traditional. As long as you have experience of other languages such as Java or C++, you won\u2019t have any difficulty understanding this.<\/li>\n<li id=\"32ec\" class=\"graf graf--li graf-after--li\">You can still wrap multiple\u00a0<code class=\"markup--code markup--li-code\">await<\/code>\u00a0calls in a single\u00a0<code class=\"markup--code markup--li-code\">try...catch<\/code>\u00a0block to handle errors in one place, if per-step error handling is not necessary.<\/li>\n<\/ul>\n<p id=\"f936\" class=\"graf graf--p graf-after--li\">There is also one flaw in this approach. Since\u00a0<code class=\"markup--code markup--p-code\">try...catch<\/code>\u00a0will catch every exception in the block, some other exceptions which not usually caught by promises will be caught. Think about this example:<\/p>\n<pre id=\"34e8\" class=\"graf graf--pre graf-after--p\">class BookModel {\r\n  fetchAll() {\r\n    cb();    \/\/ note `cb` is undefined and will result an exception\r\n    return fetch('\/books');\r\n  }\r\n}<\/pre>\n<pre id=\"9799\" class=\"graf graf--pre graf-after--pre\">try {\r\n  bookModel.fetchAll();\r\n} catch(error) {\r\n  console.log(error);  \/\/ This will print \"cb is not defined\"\r\n}<\/pre>\n<p id=\"61cb\" class=\"graf graf--p graf-after--pre\">Run this code an you will get an error\u00a0<code class=\"markup--code markup--p-code\">ReferenceError: cb is not defined<\/code>\u00a0in the console, in black color. The error was output by\u00a0<code class=\"markup--code markup--p-code\">console.log()<\/code>\u00a0but not the JavaScript itself. Sometimes this could be fatal: If\u00a0<code class=\"markup--code markup--p-code\">BookModel<\/code>\u00a0is enclosed deeply in a series of function calls and one of the call swallows the error, then it will be extremely hard to find an undefined error like this.<\/p>\n<h4 id=\"98fc\" class=\"graf graf--h4 graf-after--p\">Making functions return both\u00a0value<\/h4>\n<p id=\"4b6e\" class=\"graf graf--p graf-after--h4\">Another way for error handling is inspired by Go language. It allows async function to return both the error and the result. See this blog post for the detail:<\/p>\n<div id=\"28cf\" class=\"graf graf--mixtapeEmbed graf-after--p\"><a class=\"markup--anchor markup--mixtapeEmbed-anchor\" title=\"https:\/\/blog.grossman.io\/how-to-write-async-await-without-try-catch-blocks-in-javascript\/\" href=\"https:\/\/blog.grossman.io\/how-to-write-async-await-without-try-catch-blocks-in-javascript\/\" data-href=\"https:\/\/blog.grossman.io\/how-to-write-async-await-without-try-catch-blocks-in-javascript\/\"><strong class=\"markup--strong markup--mixtapeEmbed-strong\">How to write async await without try-catch blocks in Javascript<\/strong><br \/>\n<em class=\"markup--em markup--mixtapeEmbed-em\">ES7 Async\/await allows us as developers to write asynchronous JS code that look synchronous. In current JS version we\u2026<\/em>blog.grossman.io<\/a><\/div>\n<p id=\"dc1d\" class=\"graf graf--p graf-after--mixtapeEmbed\">In short, you can use async function like this:<\/p>\n<pre id=\"cd57\" class=\"graf graf--pre graf-after--p\"><code class=\"markup--code markup--pre-code\">[err, user] = await to(UserModel.findById(1));<\/code><\/pre>\n<p id=\"121c\" class=\"graf graf--p graf-after--pre\">Personally I don\u2019t like this approach since it brings Go style into JavaScript which feels unnatural, but in some cases this might be quite useful.<\/p>\n<h4 id=\"0bb5\" class=\"graf graf--h4 graf-after--p\">Using\u00a0.catch<\/h4>\n<p id=\"6de0\" class=\"graf graf--p graf-after--h4\">The final approach we will introduce here is to continue using\u00a0<code class=\"markup--code markup--p-code\">.catch()<\/code>.<\/p>\n<p id=\"4386\" class=\"graf graf--p graf-after--p\">Recall the functionality of\u00a0<code class=\"markup--code markup--p-code\">await<\/code>: It will wait for a promise to complete its job. Also please recall that\u00a0<code class=\"markup--code markup--p-code\">promise.catch()<\/code>\u00a0will return a promise too! So we can write error handling like this:<\/p>\n<pre id=\"e556\" class=\"graf graf--pre graf-after--p\">\/\/ books === undefined if error happens,\r\n\/\/ since nothing returned in the catch statement\r\nlet books = await bookModel.fetchAll()\r\n  .catch((error) =&gt; { console.log(error); });<\/pre>\n<p id=\"9968\" class=\"graf graf--p graf-after--pre\">There are two minor issues in this approach:<\/p>\n<ul class=\"postList\">\n<li id=\"2a1e\" class=\"graf graf--li graf-after--p\">It is a mixture of promises and async functions. You still need to understand how promises work to read it.<\/li>\n<li id=\"a7fc\" class=\"graf graf--li graf-after--li graf--trailing\">Error handling comes before normal path, which is not intuitive.<\/li>\n<\/ul>\n<\/div>\n<\/div>\n<\/section>\n<section class=\"section section--body section--last\">\n<div class=\"section-divider\">\n<hr class=\"section-divider\" \/>\n<\/div>\n<div class=\"section-content\">\n<div class=\"section-inner sectionLayout--insetColumn\">\n<h3 id=\"8e94\" class=\"graf graf--h3 graf--leading\">Conclusion<\/h3>\n<p id=\"0689\" class=\"graf graf--p graf-after--h3\">The\u00a0<code class=\"markup--code markup--p-code\">async\/await<\/code>\u00a0keywords introduced by ES7 is definitely an improvement to JavaScript asynchronous programming. It can make code easier to read and debug. However in order to use them correctly, one must completely understand promises, since they are no more than syntactic sugar, and the underlying technique is still promises.<\/p>\n<p>&nbsp;<\/p>\n<\/div>\n<\/div>\n<h4 class=\"u-lineHeightTightest\"><a class=\"ds-link ds-link--styleSubtle ui-captionStrong u-inlineBlock link link--darken link--darker is-touched\" dir=\"auto\" href=\"https:\/\/hackernoon.com\/@charleeli?source=post_header_lockup\" data-action=\"show-user-card\" data-action-source=\"post_header_lockup\" data-action-value=\"e36ca8291af4\" data-action-type=\"hover\" data-user-id=\"e36ca8291af4\" data-collection-slug=\"hacker-daily\">Charlee Li<\/a><\/h4>\n<div class=\"u-lineHeightTightest\">Full stack engineer &amp; Tech writer @ Toronto.<\/div>\n<\/section>\n","protected":false},"excerpt":{"rendered":"<p>The\u00a0async\/await\u00a0introduced by ES7 is a fantastic improvement in asynchronous programming with JavaScript. It provided an option of using synchronous style [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":86,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"site-sidebar-layout":"default","site-content-layout":"","ast-site-content-layout":"default","site-content-style":"default","site-sidebar-style":"default","ast-global-header-display":"","ast-banner-title-visibility":"","ast-main-header-display":"","ast-hfb-above-header-display":"","ast-hfb-below-header-display":"","ast-hfb-mobile-header-display":"","site-post-title":"","ast-breadcrumbs-content":"","ast-featured-img":"","footer-sml-layout":"","theme-transparent-header-meta":"","adv-header-id-meta":"","stick-header-meta":"","header-above-stick-meta":"","header-main-stick-meta":"","header-below-stick-meta":"","astra-migrate-meta-layouts":"default","ast-page-background-enabled":"default","ast-page-background-meta":{"desktop":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"ast-content-background-meta":{"desktop":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"footnotes":""},"categories":[48,44,47,29],"tags":[46,60],"class_list":["post-378","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-front-end","category-javascript","category-medium","category-programacion","tag-javascript","tag-medium"],"_links":{"self":[{"href":"https:\/\/blog.hassler.ec\/wp\/wp-json\/wp\/v2\/posts\/378","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.hassler.ec\/wp\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.hassler.ec\/wp\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.hassler.ec\/wp\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.hassler.ec\/wp\/wp-json\/wp\/v2\/comments?post=378"}],"version-history":[{"count":1,"href":"https:\/\/blog.hassler.ec\/wp\/wp-json\/wp\/v2\/posts\/378\/revisions"}],"predecessor-version":[{"id":379,"href":"https:\/\/blog.hassler.ec\/wp\/wp-json\/wp\/v2\/posts\/378\/revisions\/379"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blog.hassler.ec\/wp\/wp-json\/wp\/v2\/media\/86"}],"wp:attachment":[{"href":"https:\/\/blog.hassler.ec\/wp\/wp-json\/wp\/v2\/media?parent=378"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.hassler.ec\/wp\/wp-json\/wp\/v2\/categories?post=378"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.hassler.ec\/wp\/wp-json\/wp\/v2\/tags?post=378"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}