<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Maxim Orlov</title>
    <description>The latest articles on DEV Community by Maxim Orlov (@maximization).</description>
    <link>https://dev.to/maximization</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F295594%2F6376048f-1d76-4a41-be20-63e660c00d39.jpg</url>
      <title>DEV Community: Maxim Orlov</title>
      <link>https://dev.to/maximization</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/maximization"/>
    <language>en</language>
    <item>
      <title>One or Two-Column Resumes: Best Choice for Aspiring Web Developers</title>
      <dc:creator>Maxim Orlov</dc:creator>
      <pubDate>Wed, 22 Nov 2023 04:00:00 +0000</pubDate>
      <link>https://dev.to/maximization/one-or-two-column-resumes-best-choice-for-aspiring-web-developers-2m7b</link>
      <guid>https://dev.to/maximization/one-or-two-column-resumes-best-choice-for-aspiring-web-developers-2m7b</guid>
      <description>&lt;p&gt;&lt;em&gt;This article was originally published at &lt;a href="https://maximorlov.com/one-or-two-column-resumes/"&gt;https://maximorlov.com/one-or-two-column-resumes/&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The design of your resume can make or break your job search.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A well-designed resume stays out of the way and &lt;em&gt;effectively&lt;/em&gt; conveys your qualifications to the recruiter's scanning eye.&lt;/p&gt;

&lt;p&gt;In contrast, a poorly designed resume is &lt;em&gt;confusing&lt;/em&gt;, obscures important information, and fails to convince the recruiter to invite you for an interview.&lt;/p&gt;

&lt;p&gt;With hundreds of applications per position, you want to do everything possible to pass the initial selection phase, where most applicants are eliminated.&lt;/p&gt;

&lt;p&gt;Resume layouts typically come in two types: one-column and two-column. &lt;strong&gt;Which layout is more likely to increase your chances of securing an interview?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You might assume that a two-column layout is better, as it allows you to include more information and stand out. However, this is a &lt;em&gt;misunderstanding&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;These are the top three reasons why a two-column layout is likely hindering your job search.&lt;/p&gt;

&lt;h2&gt;
  
  
  Harder to read
&lt;/h2&gt;

&lt;p&gt;Recruiters have to go through dozens or even hundreds of resumes for a single position. It's said that &lt;strong&gt;a recruiter spends at most 10 seconds reviewing a resume.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;10 seconds! That's nothing.&lt;/p&gt;

&lt;p&gt;In those 10 seconds, your resume &lt;em&gt;must&lt;/em&gt; convince the recruiter to consider you for the position. That's not a small feat!&lt;/p&gt;

&lt;p&gt;Your resume should be as &lt;em&gt;easy to scan&lt;/em&gt; as possible, with minimal friction to the recruiter's eyes. A two-column layout complicates this by &lt;strong&gt;breaking up the visual field&lt;/strong&gt;, requiring more focus and time to read — time you can't afford to lose.&lt;/p&gt;

&lt;p&gt;Moreover, recruiters are more accustomed to scanning one-column layouts. This familiarity works in your favor, as the easier your resume is to scan, the more likely a recruiter will learn about your qualifications and consider you for the next round.&lt;/p&gt;

&lt;h2&gt;
  
  
  Formatting issues
&lt;/h2&gt;

&lt;p&gt;Two-column layouts are challenging to format correctly. Managing whitespace and ensuring a cohesive flow is more complex than in a one-column layout.&lt;/p&gt;

&lt;p&gt;Furthermore, a two-column layout is not update-friendly. Tailoring your resume for each job application (which you should!) can disrupt the balance between the columns. You're then left &lt;strong&gt;juggling the symmetry between the left and right column.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A two-column layout also is more prone to being distorted when saved in different file formats. The last thing you want is to send a jumbled mess to recruiters.&lt;/p&gt;

&lt;p&gt;Formatting a one-column resume is already a challenge; going for a two-column layout adds unnecessary complexity.&lt;/p&gt;

&lt;h2&gt;
  
  
  Not ATS friendly
&lt;/h2&gt;

&lt;p&gt;Many companies use Applicant Tracking Systems (ATS) to streamline their hiring process. An ATS parses resumes to simplify the recruiter's review. Some systems even &lt;em&gt;score resumes&lt;/em&gt; on their match potential.&lt;/p&gt;

&lt;p&gt;An ATS typically reads a resume from left to right, top to bottom. A two-column layout disrupts this logical flow, &lt;a href="https://www.jobscan.co/blog/resume-tables-columns-ats/"&gt;making correct parsing more challenging&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If the ATS can't fully interpret your resume, it may overlook key keywords, resulting in a lower score.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In a competitive job market, where hundreds of candidates apply for a single position, many applications are &lt;em&gt;automatically rejected&lt;/em&gt; by these systems. You want to avoid automatic rejection and ensure your efforts are seen.&lt;/p&gt;

&lt;p&gt;While ATS technology has improved and some have gotten better at parsing two-column layouts, you can't be certain which system will process your resume. Why take the risk?&lt;/p&gt;

&lt;h2&gt;
  
  
  Want to impress? Focus on content
&lt;/h2&gt;

&lt;p&gt;Impress recruiters with your &lt;em&gt;qualifications&lt;/em&gt;, not a fancy resume design.&lt;/p&gt;

&lt;p&gt;Emphasize the impact of your work. Describe how your efforts benefited your team and led to measurable achievements. Use numbers to reinforce these points.&lt;/p&gt;

&lt;p&gt;Highlight projects, &lt;a href="https://maximorlov.com/unfinished-projects-on-resume/"&gt;even unfinished ones&lt;/a&gt;, that demonstrate your skills.&lt;/p&gt;

&lt;p&gt;Ensure your resume clearly communicates why you are suited for the specific job you're applying for, including technologies and skills mentioned in the job description.&lt;/p&gt;

&lt;p&gt;In conclusion, a &lt;strong&gt;one-column layout is the best choice&lt;/strong&gt; for your resume. It's easier to read, update, and more likely to pass the ATS, giving you a real chance at the job.&lt;/p&gt;

&lt;h2&gt;
  
  
  Craft a resume that's impossible to ignore
&lt;/h2&gt;

&lt;p&gt;Take the next step towards securing your dream job with a comprehensive resume checklist. Made &lt;em&gt;specifically&lt;/em&gt; for aspiring software engineers, this FREE checklist (featuring 35+ points) ensures you not only &lt;strong&gt;stand out&lt;/strong&gt; but also effectively &lt;strong&gt;showcase your skills&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;By following these guidelines, you'll craft a resume that grabs recruiters' attention, highlights your unique talents, and &lt;em&gt;increases&lt;/em&gt; your chances of breaking into tech. I guarantee that if your resume ticks all the boxes on this checklist, you'll &lt;strong&gt;start receiving more interview invitations&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Simply enter your email &lt;a href="https://maximorlov.com/one-or-two-column-resumes/"&gt;below the original article&lt;/a&gt;, and I'll send the checklist straight to your inbox.&lt;/p&gt;

</description>
      <category>career</category>
      <category>webdev</category>
      <category>beginners</category>
      <category>codenewbie</category>
    </item>
    <item>
      <title>ESLint Setup in Node.js: A Detailed Guide</title>
      <dc:creator>Maxim Orlov</dc:creator>
      <pubDate>Tue, 10 Oct 2023 07:48:05 +0000</pubDate>
      <link>https://dev.to/maximization/eslint-setup-in-nodejs-a-detailed-guide-for-beginners-1h7l</link>
      <guid>https://dev.to/maximization/eslint-setup-in-nodejs-a-detailed-guide-for-beginners-1h7l</guid>
      <description>&lt;p&gt;&lt;em&gt;This article was originally published at &lt;a href="https://maximorlov.com/eslint-setup-nodejs-detailed-guide-beginners/" rel="noopener noreferrer"&gt;https://maximorlov.com/eslint-setup-nodejs-detailed-guide-beginners/&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;A code linter can simplify your developer life by a lot. I couldn't imagine coding without one.&lt;/p&gt;

&lt;p&gt;It immediately catches many syntax errors and potential bugs &lt;em&gt;as I type&lt;/em&gt;. There's no need to wait until deploying to production to find out my code isn't working properly.&lt;/p&gt;

&lt;p&gt;This rapid feedback loop empowers me to develop &lt;em&gt;faster&lt;/em&gt; and with more &lt;em&gt;confidence&lt;/em&gt;, knowing that I have a trustworthy tool watching my back.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Wondering how to start using a code linter with Node.js?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In this tutorial, I'll walk you through the step-by-step process of adding ESLint, the most popular JavaScript linter, into your project so you can start benefiting from it &lt;em&gt;right away&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Requirements&lt;/strong&gt;&lt;br&gt;
This tutorial assumes no prior knowledge of ESLint and starts from the basics.&lt;/p&gt;

&lt;p&gt;I assume you already have a Node.js project and consequently, an existing &lt;code&gt;package.json&lt;/code&gt; file (set up with &lt;code&gt;npm init&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Goals&lt;/strong&gt;&lt;br&gt;
By the end of this tutorial, you'll have a basic ESLint setup up and running. I'll also give you additional resources so you can delve deeper and further customize the linter if you want to.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Overview&lt;/strong&gt;&lt;br&gt;
Here's what we're going to do:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Install &amp;amp; configure ESLint&lt;/strong&gt; in your Node.js project&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Integrate ESLint with VSCode&lt;/strong&gt; for real-time feedback within your editor&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Without further ado, let's dive in.&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 1 – Install &amp;amp; configure ESLint in a Node.js project
&lt;/h2&gt;

&lt;p&gt;ESLint offers an interactive CLI package that simplifies installation and configuration. It prompts a series of questions about your project and preferences.&lt;/p&gt;

&lt;p&gt;At the root of your project folder, open the terminal and type:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm init @eslint/config
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here are the questions you'll face:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;How would you like to use ESLint?&lt;/strong&gt; - Select the second option: "To check syntax and find problems". ESLint can also enforce a coding style but for that, I recommend using &lt;a href="https://prettier.io/" rel="noopener noreferrer"&gt;Prettier&lt;/a&gt; instead.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;What type of modules does your project use?&lt;/strong&gt; - Choose the option that matches your project: ES Modules (option 1) with &lt;code&gt;import&lt;/code&gt; or CommonJS (option 2) with &lt;code&gt;require&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Which framework does your project use?&lt;/strong&gt; - Since we're working with a Node.js project, select "None of these".&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Does your project use TypeScript?&lt;/strong&gt; - Pick "Yes" if applicable. Otherwise, opt for "No". If you're unsure, it's likely "No".&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Where does your code run?&lt;/strong&gt; - This is a multiple-choice question and "Browser" will be pre-selected. Deselect "Browser" and select "Node".&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;What format do you want your config file to be in?&lt;/strong&gt; - Pick "JavaScript". JSON configurations lack comment functionality, and YAML demands familiarity with its syntax.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Would you like to install them now?&lt;/strong&gt; - Depending on your earlier choices the dependencies will vary. At a minimum, the setup wizard will introduce &lt;code&gt;eslint@latest&lt;/code&gt; to your project. Click "Yes".&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Which package manager do you want to use?&lt;/strong&gt; - Choose "npm".&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Upon completion, the wizard will install dependencies and generate a &lt;code&gt;.eslintrc.js&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnoiw11h8y1btqo87lkyu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnoiw11h8y1btqo87lkyu.png" alt="Screenshot of a file explorer and a code snippet showing package dependencies." width="800" height="484"&gt;&lt;/a&gt;&lt;/p&gt;
File structure highlighting `.eslintrc.js` and the corresponding version of `eslint` in the `package.json` file



&lt;p&gt;Inspect your &lt;code&gt;package.json&lt;/code&gt; file. You'll find the latest version of &lt;code&gt;eslint&lt;/code&gt; listed under &lt;code&gt;devDependencies&lt;/code&gt;. ESLint is a development dependency since you only need it during development to enhance your workflow. Production environments often omit development dependencies to speed up deployments.&lt;/p&gt;

&lt;p&gt;If you opted for TypeScript, the wizard would also have added the &lt;code&gt;@typescript-eslint/eslint-plugin&lt;/code&gt; and &lt;code&gt;@typescript-eslint/parser&lt;/code&gt; packages. The former is an ESLint plugin with additional linting rules made possible by strict typing. The latter enables ESLint to comprehend TypeScript syntax.&lt;/p&gt;

&lt;p&gt;Another addition to your project is the &lt;code&gt;.eslintrc.js&lt;/code&gt; file. Inside, you'll find configurations that may differ based on your responses.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5btox8lnmu7spr8qkgra.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5btox8lnmu7spr8qkgra.png" alt="Screenshot of a code snippet showing ESLint configuration settings." width="800" height="947"&gt;&lt;/a&gt;&lt;/p&gt;
ESLint configuration specifying environment settings, extending recommended rules, and parser options



&lt;p&gt;Let's delve deeper into each configuration so you understand what's going on. Regardless of your responses to the setup questions, these are the configurations you'll encounter:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;env.es2021&lt;/code&gt; - Introduces language-specific global variables from ECMAScript 2021. Recent additions to the language include &lt;code&gt;BigInt&lt;/code&gt;, &lt;code&gt;Atomics&lt;/code&gt;, and &lt;code&gt;AggregateError&lt;/code&gt;. Why not 2022 or 2023? Because those ECMAScript versions haven't introduced new global variables. You could add &lt;code&gt;es2023&lt;/code&gt; to your config, but it wouldn't make any difference. &lt;a href="https://github.com/eslint/eslint/blob/main/conf/globals.js#L116" rel="noopener noreferrer"&gt;Source&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;env.node&lt;/code&gt; - Includes global variables specific to Node.js, such as &lt;code&gt;process&lt;/code&gt; and &lt;code&gt;AbortController&lt;/code&gt;. &lt;a href="https://github.com/sindresorhus/globals/blob/main/globals.json#L1207" rel="noopener noreferrer"&gt;Source&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;extends&lt;/code&gt; - Enables additional rules recommended by ESLint under &lt;code&gt;eslint:recommended&lt;/code&gt;. &lt;a href="https://eslint.org/docs/latest/rules/" rel="noopener noreferrer"&gt;ESLint Rules documentation&lt;/a&gt; &amp;amp; &lt;a href="https://github.com/eslint/eslint/blob/main/packages/js/src/configs/eslint-recommended.js" rel="noopener noreferrer"&gt;Source&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;overrides&lt;/code&gt; - Allows configurations from this file to be overridden for specific files. Essentially, this is to ensure the configuration file itself (&lt;code&gt;.eslintrc.js&lt;/code&gt;) is linted properly. &lt;a href="https://eslint.org/docs/latest/use/configure/configuration-files#how-do-overrides-work" rel="noopener noreferrer"&gt;ESLint Overrides documentation&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;overrides[0].env.node&lt;/code&gt; - Similar to the main &lt;code&gt;env.node&lt;/code&gt; configuration, it adds Node.js-specific global variables.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;overrides[0].files&lt;/code&gt; - Specifies the files for which the configuration should be overridden.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;overrides[0].parserOptions.sourceType&lt;/code&gt; - Directs the parser to interpret the file as a &lt;code&gt;script&lt;/code&gt; (CommonJS).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;parserOptions.ecmaVersion&lt;/code&gt; - Instructs ESLint to parse the codebase using the latest ECMAScript version.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;rules&lt;/code&gt; - Initially, this is an empty object. Later on, as you expand your linting preferences, this is where you'll define custom rules. &lt;a href="https://eslint.org/docs/latest/rules/" rel="noopener noreferrer"&gt;ESLint Rules Documentation&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;If you opted for ES Modules&lt;/strong&gt;, you'll see this additional configuration:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;parserOptions.sourceType&lt;/code&gt; - Informs the parser to interpret all files as &lt;code&gt;module&lt;/code&gt; (ES Modules).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;If you chose CommonJS:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;env.commonjs&lt;/code&gt; - Includes CommonJS global variables, such as &lt;code&gt;require&lt;/code&gt; and &lt;code&gt;module&lt;/code&gt;. &lt;a href="https://github.com/eslint/eslint/blob/main/conf/globals.js#L12" rel="noopener noreferrer"&gt;Source&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;If your project uses TypeScript&lt;/strong&gt;, you'll see these configurations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;extends&lt;/code&gt; - In addition to the recommended rules from ESLint, rules tailored for TypeScript are enabled with &lt;code&gt;plugin:@typescript-eslint/recommended&lt;/code&gt;. &lt;a href="https://typescript-eslint.io/rules/" rel="noopener noreferrer"&gt;TypeScript ESLint Rules documentation&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;parser&lt;/code&gt; - Uses the TypeScript parser to convert TypeScript code so ESLint can understand it. &lt;a href="https://eslint.org/docs/latest/use/configure/parser" rel="noopener noreferrer"&gt;ESLint Parser documentation&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;plugins&lt;/code&gt; - Imports the &lt;code&gt;@typescript-eslint&lt;/code&gt; plugin which gives you access to TypeScript-specific rules and its custom parser. &lt;a href="https://typescript-eslint.io/getting-started/" rel="noopener noreferrer"&gt;TypeScript ESLint documentation&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now, you're all set!&lt;/p&gt;

&lt;p&gt;In your terminal, you can run &lt;code&gt;npx eslint .&lt;/code&gt; to lint your project. If there are issues, they'll be displayed in your console.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frmsq7qwaf8o64i9ogmfe.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frmsq7qwaf8o64i9ogmfe.png" alt="Screenshot of ESLint error messages indicating  raw `width` endraw  is not defined in a file named  raw `generateSrcset.js` endraw ." width="800" height="200"&gt;&lt;/a&gt;&lt;/p&gt;
ESLint error messages in the console



&lt;p&gt;ESLint can even automatically fix certain types of errors. Add the &lt;code&gt;--fix&lt;/code&gt; flag to the command: &lt;code&gt;npx eslint --fix .&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;To learn more about ESLint, the &lt;a href="https://eslint.org/docs/latest/" rel="noopener noreferrer"&gt;ESLint documentation&lt;/a&gt; is an excellent resource.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2 – Integrate ESLint with VSCode
&lt;/h2&gt;

&lt;p&gt;To get continuous feedback from ESLint as you code, rather than running the command repeatedly, you can integrate ESLint into your editor. I'll cover integration with VSCode, given its popularity.&lt;/p&gt;

&lt;p&gt;Simply download the &lt;a href="https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint" rel="noopener noreferrer"&gt;ESLint extension for VSCode&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Once the extension is installed, ESLint errors will be directly highlighted in your editor.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6pt38r10cljcnd752pzp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6pt38r10cljcnd752pzp.png" alt="Screenshot of a code snippet for generating a srcset attribute with highlighted ESLint warning about the variable  raw `width` endraw  being not defined." width="800" height="317"&gt;&lt;/a&gt;&lt;/p&gt;
ESLint integration in VSCode highlighting errors in the editor



&lt;p&gt;And that's a wrap!&lt;/p&gt;

&lt;p&gt;From now on you'll always have ESLint watching your back and preventing you from making silly mistakes. After all, we're all human and make mistakes :).&lt;/p&gt;

&lt;p&gt;Continue reading to discover &lt;a href="https://maximorlov.com/linting-rules-for-asynchronous-code-in-javascript/" rel="noopener noreferrer"&gt;14 ESLint rules for improving your asynchronous JavaScript code&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Happy coding! 🎭&lt;/p&gt;

&lt;h2&gt;
  
  
  Write clean code. Stay ahead of the curve.
&lt;/h2&gt;

&lt;p&gt;Every other Tuesday, I share tips on how to build robust Node.js applications. Join a community of developers committed to advancing their careers and gain the knowledge &amp;amp; skills you need to succeed. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://maximorlov.kit.com/0076aaf499" class="ltag_cta ltag_cta--branded" rel="noopener noreferrer"&gt;Subscribe for success!&lt;/a&gt;
&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>node</category>
      <category>webdev</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Understanding "Property of Undefined" TypeError in JavaScript</title>
      <dc:creator>Maxim Orlov</dc:creator>
      <pubDate>Fri, 15 Sep 2023 03:53:04 +0000</pubDate>
      <link>https://dev.to/maximization/understanding-property-of-undefined-typeerror-in-javascript-168f</link>
      <guid>https://dev.to/maximization/understanding-property-of-undefined-typeerror-in-javascript-168f</guid>
      <description>&lt;p&gt;&lt;em&gt;This article was originally published at &lt;a href="https://maximorlov.com/understanding-property-of-undefined-typeerror-in-javascript/" rel="noopener noreferrer"&gt;https://maximorlov.com/understanding-property-of-undefined-typeerror-in-javascript/&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;You're likely here because you've run across this all-too-familiar JavaScript error message:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;TypeError: can't access property "value" of undefined&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;While the message seems clear, its &lt;em&gt;wording&lt;/em&gt; can be misleading and leave you confused.&lt;/p&gt;

&lt;p&gt;You're not alone, even seasoned developers occasionally trip up when they encounter this.&lt;/p&gt;

&lt;p&gt;This is a common error in JavaScript, and you'll see it frequently in your web development career. The sooner you understand it, the &lt;em&gt;less time&lt;/em&gt; you'll waste chasing the bug in the wrong places.&lt;/p&gt;

&lt;p&gt;Let's examine this error message and reveal what it's &lt;em&gt;really&lt;/em&gt; trying to tell us.&lt;/p&gt;

&lt;h2&gt;
  
  
  Decoding the error message
&lt;/h2&gt;

&lt;p&gt;To better understand this error, or its equivalent, &lt;code&gt;cannot read properties of undefined (reading "value")&lt;/code&gt;, it's crucial to analyze the error message in detail.&lt;/p&gt;

&lt;p&gt;The irony is that the message contains all the information you need—it's just that, more often than not, developers gloss over it.&lt;/p&gt;

&lt;p&gt;Suppose you have a &lt;code&gt;user&lt;/code&gt; variable that's supposed to be an object and you're trying to access the &lt;code&gt;name&lt;/code&gt; property:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// TypeError: can't access property "name" of undefined&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At first glance, you might suspect that &lt;code&gt;name&lt;/code&gt; is undefined.&lt;/p&gt;

&lt;p&gt;However, if that were the case, JavaScript would simply return &lt;code&gt;undefined&lt;/code&gt;. Nothing wrong with that:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// undefined&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In reality, the issue lies one level higher—it's the &lt;em&gt;parent&lt;/em&gt; &lt;code&gt;user&lt;/code&gt; object that's &lt;code&gt;undefined&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// undefined&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// TypeError: can't access property "name" of undefined&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When you attempt to access a property on &lt;code&gt;undefined&lt;/code&gt; type in JavaScript, the program throws a TypeError.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypeError" rel="noopener noreferrer"&gt;MDN describes a TypeError&lt;/a&gt; as:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The &lt;code&gt;TypeError&lt;/code&gt; object represents an error when an operation could not be performed, typically (but not exclusively) when a value is not of the expected type.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So we end up doing &lt;code&gt;undefined.name&lt;/code&gt; which doesn't make sense because &lt;code&gt;undefined&lt;/code&gt; is not of type &lt;code&gt;Object&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding the hidden message
&lt;/h2&gt;

&lt;p&gt;When the error says &lt;code&gt;can't access property "name" of undefined&lt;/code&gt;, it's really saying: "Hey, the object you're trying to read &lt;code&gt;name&lt;/code&gt; from? Yeah, that one's &lt;code&gt;undefined&lt;/code&gt;."&lt;/p&gt;

&lt;p&gt;You shouldn't focus on &lt;code&gt;name&lt;/code&gt;, but on its parent object. It's about where you're pulling &lt;code&gt;name&lt;/code&gt; from.&lt;/p&gt;

&lt;p&gt;What confuses many developers is that the error message doesn't show the name of the parent object which is causing the issue. Most developers tend to skim through the error, catch sight of the variable name, and wrongly assume that's where the problem lies.&lt;/p&gt;

&lt;h2&gt;
  
  
  Line and column numbers are your friends
&lt;/h2&gt;

&lt;p&gt;Error messages come with a stack trace that does us a favor by displaying the line and column number where the error originated. &lt;strong&gt;The key to tracing any bug is to read the line and column numbers in the stack trace&lt;/strong&gt; and navigate to that location in your project.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: This information is generally reliable unless you're dealing with minified or transpiled code without source maps.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For example, when I run this code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I get the following output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;TypeError: Cannot &lt;span class="nb"&gt;read &lt;/span&gt;properties of undefined &lt;span class="o"&gt;(&lt;/span&gt;reading &lt;span class="s1"&gt;'value'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    at file:///Users/maxim/Code/playground/test.js:2:15
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The error message tells me the problem lies in the test.js file on line 2, column 15. This points directly to the dot notation, offering a clue about where the problem is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
          &lt;span class="c1"&gt;// ^ line 2, column 15&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Question your assumptions
&lt;/h2&gt;

&lt;p&gt;Ultimately, &lt;strong&gt;effective debugging involves questioning your initial assumptions&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Within that questioning, we often find that we've made a wrong assumption that led us to reason about the code in the wrong way.&lt;/p&gt;

&lt;p&gt;A bug is a difference between what we &lt;em&gt;expect&lt;/em&gt; the program to do and what it &lt;em&gt;actually&lt;/em&gt; does.&lt;/p&gt;

&lt;p&gt;So the next time this confusing error pops up, you'll know exactly what to look for. It's this level of understanding that sets you apart as a developer.&lt;/p&gt;

&lt;p&gt;Remember, we all make mistakes, but it's how we learn from them that defines us as developers. Happy debugging! 🐞 🚫&lt;/p&gt;

&lt;h2&gt;
  
  
  Write clean code. Stay ahead of the curve.
&lt;/h2&gt;

&lt;p&gt;Every other Tuesday, I share tips on how to build robust Node.js applications. Join a community of developers committed to advancing their careers and gain the knowledge &amp;amp; skills you need to succeed. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://maximorlov.kit.com/0076aaf499" class="ltag_cta ltag_cta--branded" rel="noopener noreferrer"&gt;Subscribe for success!&lt;/a&gt;
&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>productivity</category>
      <category>learning</category>
    </item>
    <item>
      <title>Navigate New Codebases Like a Seasoned Pro</title>
      <dc:creator>Maxim Orlov</dc:creator>
      <pubDate>Mon, 04 Sep 2023 05:08:49 +0000</pubDate>
      <link>https://dev.to/maximization/navigate-new-codebases-like-a-seasoned-pro-1ho0</link>
      <guid>https://dev.to/maximization/navigate-new-codebases-like-a-seasoned-pro-1ho0</guid>
      <description>&lt;p&gt;&lt;em&gt;This article was originally published at &lt;a href="https://maximorlov.com/navigating-new-codebases/" rel="noopener noreferrer"&gt;https://maximorlov.com/navigating-new-codebases/&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;You've landed your first web development job or internship, and you're excited to get your hands dirty in the codebase. Congratulations! 🎉&lt;/p&gt;

&lt;p&gt;But wait... You're dropped into a colossal project and told to "just mess around with it"? How are you supposed to make sense of &lt;strong&gt;thousands of lines of code&lt;/strong&gt;?&lt;/p&gt;

&lt;p&gt;You're probably lost and scared that you won't be able to pull it off, especially if you're working remotely. It's not like you can have someone pop by your shoulder and give you friendly advice.&lt;/p&gt;

&lt;p&gt;No worries, though. &lt;strong&gt;This feeling is natural and it &lt;em&gt;will pass&lt;/em&gt;.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Follow these &lt;strong&gt;4 tips&lt;/strong&gt; while you navigate a new codebase and you will ace your new job! 💪&lt;/p&gt;

&lt;h2&gt;
  
  
  Tip 1: Create a map
&lt;/h2&gt;

&lt;p&gt;The first time looking at a massive codebase can be daunting. You might feel like you're in the middle of a labyrinth with no escape.&lt;/p&gt;

&lt;p&gt;This is why mapping is &lt;em&gt;crucial&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Grab a pen and paper, or go digital if you prefer. Create a flowchart that outlines how different modules and components interact with one another. This could be as simple as "User Input → Form Validation → Database" or as complicated as a multi-layer API structure. The goal is to give yourself a roadmap, or a cheat sheet if you will, to refer back to.&lt;/p&gt;

&lt;p&gt;Think of it as mapping out your favorite video game. &lt;strong&gt;It helps you understand where you are and where you need to go.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;After creating the initial flowchart, keep refining it. Whenever you understand a new aspect of the code, update your map. The process is ongoing, and your understanding of the codebase will evolve.&lt;/p&gt;

&lt;p&gt;The map will become an indispensable resource as you dive deeper. And you know what? Your future self and potential teammates will thank you for it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tip 2: Add small features
&lt;/h2&gt;

&lt;p&gt;You might be wondering, "Why should I add features to a project I don't understand yet?".&lt;/p&gt;

&lt;p&gt;Well, the beauty is in the &lt;em&gt;doing&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;When you take the bold step to insert a small widget or perhaps modify a piece of existing code, you engage with the system in a very practical way. This is where the rubber meets the road. As you succeed in adding small features, &lt;strong&gt;you'll gain confidence&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Plus, by doing so, you'll inevitably encounter various parts of the codebase, which helps your understanding of it.&lt;/p&gt;

&lt;p&gt;Don't worry if the feature you're adding doesn't bring about world peace. The goal is &lt;em&gt;learning&lt;/em&gt;, not perfection. Over time, these little additions will empower you to understand larger structures and even refactor code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tip 3: Read and comment
&lt;/h2&gt;

&lt;p&gt;Code isn't just a set of instructions for a computer. It's a language that developers communicate in.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;So treat the codebase like a book — &lt;em&gt;read it, ponder it, question it&lt;/em&gt;.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Try to understand the developer's intentions. Why did they use a for-loop here instead of a while-loop? What's the reason for caching this specific data? These are the types of questions that will help you dig deeper into the code's logic and purpose.&lt;/p&gt;

&lt;p&gt;Don't underestimate the power of commenting. Write your thoughts and questions directly in the code as comments. If you're wondering why a particular function is structured a certain way, write it down. These comments act like sticky notes that you or another developer can refer back to. They're the questions you'll ask in your next team meeting or during a pair programming session.&lt;/p&gt;

&lt;p&gt;By annotating the codebase, you make it interactive — a living, breathing document that helps everyone involved.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tip 4: Ask (many) questions
&lt;/h2&gt;

&lt;p&gt;It's not only okay to ask questions, it's encouraged!&lt;/p&gt;

&lt;p&gt;Think you don't even know what to ask? Well, you do! Write down anything you don't understand and can't find in documentation (if there's any). There's no such thing as a stupid question when you're learning. The only stupid thing is not asking and remaining in the dark.&lt;/p&gt;

&lt;p&gt;If you're working remotely it can feel isolating, and the lack of in-person interactions can leave you second-guessing your every move. But remember, remote work doesn't mean less communication. It means &lt;em&gt;more&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Got questions? Jot 'em down.&lt;/strong&gt; Not sure how to extend a form or why a piece of code is doing what it's doing? Mark it and discuss it with a colleague.&lt;/p&gt;

&lt;h2&gt;
  
  
  Don't let fear get the best of you
&lt;/h2&gt;

&lt;p&gt;The project might be as complex as a full-fledged slot game or a robust e-commerce site, but don't let that intimidate you. Seasoned developers also get this overwhelmed feeling. The difference? &lt;strong&gt;They know it'll pass because they've been through it before.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You &lt;em&gt;too&lt;/em&gt; will navigate through the maze of code, functions, and algorithms.&lt;/p&gt;

&lt;p&gt;So map out the code, add small features, comment generously, and communicate! Don't bottle up your questions, ask them.&lt;/p&gt;

&lt;p&gt;You're not an imposter. You're an explorer charting new territories, and like any great explorer, it's okay to ask for directions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;So go on, roll up your sleeves, and dig in!&lt;/strong&gt; 🚀&lt;/p&gt;

&lt;h2&gt;
  
  
  Write clean code. Stay ahead of the curve.
&lt;/h2&gt;

&lt;p&gt;Every other Tuesday, I share tips on how to build robust Node.js applications. Join a community of developers committed to advancing their careers and gain the knowledge &amp;amp; skills you need to succeed. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://maximorlov.kit.com/0076aaf499" class="ltag_cta ltag_cta--branded" rel="noopener noreferrer"&gt;Subscribe for success!&lt;/a&gt;
&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>programming</category>
      <category>webdev</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Unfinished Projects on Resume: Wise or Not?</title>
      <dc:creator>Maxim Orlov</dc:creator>
      <pubDate>Thu, 27 Jul 2023 05:05:00 +0000</pubDate>
      <link>https://dev.to/maximization/unfinished-projects-on-resume-wise-or-not-2gef</link>
      <guid>https://dev.to/maximization/unfinished-projects-on-resume-wise-or-not-2gef</guid>
      <description>&lt;p&gt;&lt;em&gt;This article was originally published at &lt;a href="https://maximorlov.com/unfinished-projects-on-resume/"&gt;https://maximorlov.com/unfinished-projects-on-resume/&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Sometimes, you're working on a project or app and itching to showcase it on your resume, but there's a catch – the project &lt;em&gt;isn't finished&lt;/em&gt; yet.&lt;/p&gt;

&lt;p&gt;So you might ask yourself, "At what stage in the development of an app is it appropriate to feature it on my resume? Should I include an incomplete project at all?"&lt;/p&gt;

&lt;p&gt;To answer these questions, you'll need to consider two things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The project's contribution to your &lt;em&gt;knowledge&lt;/em&gt; and &lt;em&gt;growth&lt;/em&gt; as a web developer.&lt;/li&gt;
&lt;li&gt;The &lt;em&gt;opportunity cost&lt;/em&gt; of including the project on your resume (i.e., what else didn't make the cut).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let's discuss each of these points in more detail.&lt;/p&gt;

&lt;h2&gt;
  
  
  What have you learned from the project?
&lt;/h2&gt;

&lt;p&gt;In an ideal world, only fully completed projects should make the cut for your resume.&lt;/p&gt;

&lt;p&gt;However, if you're feeling the need to bolster your resume a little bit, especially if you're applying for jobs, it's acceptable to include projects that are still under development.&lt;/p&gt;

&lt;p&gt;The key lies in their ability to demonstrate your competencies and expertise.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A good time to include an unfinished project is when you've learned enough from it that you could confidently talk about it in a job interview&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Keep in mind that &lt;em&gt;anything&lt;/em&gt; on your resume is fair game for interview discussions. Be prepared to talk about your project and the challenges you've encountered along the way, as well as the solutions you've implemented.&lt;/p&gt;

&lt;p&gt;This means the project will most likely have some noteworthy completed features.&lt;/p&gt;

&lt;h2&gt;
  
  
  What else are you excluding?
&lt;/h2&gt;

&lt;p&gt;Furthermore, it's important to weigh the opportunity cost of adding an unfinished project to your resume.&lt;/p&gt;

&lt;p&gt;A typical resume is limited to &lt;em&gt;one page&lt;/em&gt;. Your education, skills, and work history have already staked their claim to that precious space.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If squeezing in this project implies omitting something else, ensure the project offers a much better representation of your skills&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Your resume is all about putting your &lt;em&gt;best foot forward&lt;/em&gt;. You want to highlight your most impressive achievements. Think of it as cherry-picking your standout accomplishments to make a strong impression on potential employers.&lt;/p&gt;

&lt;p&gt;So, if you consider the project to be a significant achievement, given everything else on your resume, then it's likely a good addition.&lt;/p&gt;

&lt;p&gt;However, if your project is still in its infancy and lacks substantial features or progress, it's best to hold off on adding it to your resume.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Circling back to the initial question, "At what stage of an app's development is it suitable to include on a resume?" consider these two points:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Has your progress with the app reached a stage where you can discuss challenges you've faced and solutions you've implemented? Could you have an &lt;em&gt;insightful conversation&lt;/em&gt; about the project in an interview?&lt;/li&gt;
&lt;li&gt;If adding this project to your resume means sacrificing something else, does the app offer a &lt;em&gt;stronger representation of your skills&lt;/em&gt; than what you're leaving out?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;By answering these questions for yourself, you'll be able to make an informed decision about whether or not to feature an unfinished project on your resume.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Do you want to have an attractive portfolio? Would you rather focus on the back end instead of fiddling with CSS?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I'm releasing a collection of portfolio projects that include a beautiful and complete front end. &lt;a href="https://maximorlov.com/backend-portfolio-projects-no-css/"&gt;&lt;strong&gt;Learn more →&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>webdev</category>
      <category>career</category>
      <category>beginners</category>
      <category>interview</category>
    </item>
    <item>
      <title>Should You Use char, varchar, or text in PostgreSQL?</title>
      <dc:creator>Maxim Orlov</dc:creator>
      <pubDate>Wed, 08 Feb 2023 18:30:00 +0000</pubDate>
      <link>https://dev.to/maximization/should-you-use-char-varchar-or-text-in-postgresql-16n6</link>
      <guid>https://dev.to/maximization/should-you-use-char-varchar-or-text-in-postgresql-16n6</guid>
      <description>&lt;p&gt;&lt;em&gt;This article was originally published at &lt;a href="https://maximorlov.com/char-varchar-text-postgresql/" rel="noopener noreferrer"&gt;https://maximorlov.com/char-varchar-text-postgresql/&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;When designing a database schema, you have to choose the correct data types for the data you're expecting to store.&lt;/p&gt;

&lt;p&gt;When it comes to strings, PostgreSQL has not just one, but &lt;em&gt;three&lt;/em&gt; data types to choose from: &lt;code&gt;char(n)&lt;/code&gt;, &lt;code&gt;varchar(n)&lt;/code&gt;, and &lt;code&gt;text&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;What's the difference between them, and &lt;strong&gt;which one should you choose?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;By the end of this article, you will know &lt;em&gt;exactly&lt;/em&gt; how the three data types differ, and which one you should use.&lt;/p&gt;

&lt;h2&gt;
  
  
  The 3 data types for strings in PostgreSQL
&lt;/h2&gt;

&lt;p&gt;PostgreSQL gives you three data types to store strings: &lt;code&gt;char(n)&lt;/code&gt;, &lt;code&gt;varchar(n)&lt;/code&gt;, and &lt;code&gt;text&lt;/code&gt;. These are the defining characteristics of each data type:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;char(n)&lt;/code&gt;&lt;/strong&gt; (or &lt;code&gt;character(n)&lt;/code&gt;) has a &lt;em&gt;fixed&lt;/em&gt; length of N, where N is the number of characters. When you store a string with less than N characters, the string will be space-padded on the right. Attempting to store a string with more than N characters will result in an error.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;varchar(n)&lt;/code&gt;&lt;/strong&gt; (or &lt;code&gt;character varying(n)&lt;/code&gt;), like the name implies, has a &lt;em&gt;varying&lt;/em&gt; character length not exceeding N. Unlike &lt;code&gt;char(n)&lt;/code&gt;, &lt;code&gt;varchar(n)&lt;/code&gt; doesn't add padding to strings with less than N characters. Similar to &lt;code&gt;char(n)&lt;/code&gt;, the N character length is enforced on inserts and updates.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;text&lt;/code&gt;&lt;/strong&gt; can store strings of any length. There is &lt;em&gt;no maximum limit&lt;/em&gt; on the number of characters, and padding is never applied.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: PostgreSQL allows you to use &lt;code&gt;varchar&lt;/code&gt; (without length &lt;code&gt;n&lt;/code&gt;), in which case it's equivalent to &lt;code&gt;text&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  When should you use &lt;code&gt;char(n)&lt;/code&gt;, &lt;code&gt;varchar(n)&lt;/code&gt;, or &lt;code&gt;text&lt;/code&gt;?
&lt;/h2&gt;

&lt;p&gt;There are two reasons why you might consider using &lt;code&gt;char(n)&lt;/code&gt; or &lt;code&gt;varchar(n)&lt;/code&gt; instead of &lt;code&gt;text&lt;/code&gt;: better performance and enforcing a maximum length. Let's examine both.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Performance&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://www.postgresql.org/docs/current/datatype-character.html" rel="noopener noreferrer"&gt;PostgreSQL documentation&lt;/a&gt; says the following about the performance difference between the three data types:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;There is no performance difference among these three types, ... . While char(n) has performance advantages in some other database systems, there is no such advantage in PostgreSQL;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Moreover, &lt;a href="https://wiki.postgresql.org/wiki/Don%27t_Do_This#Don.27t_use_varchar.28n.29_by_default" rel="noopener noreferrer"&gt;PostgresSQL Wiki&lt;/a&gt; says storing the same string into the three data types will use the same amount of space:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If you insert the same string into the three field types they will take up exactly the same amount of space.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Therefore, &lt;strong&gt;using &lt;code&gt;char(n)&lt;/code&gt; or &lt;code&gt;varchar(n)&lt;/code&gt; over &lt;code&gt;text&lt;/code&gt; has &lt;em&gt;no performance benefit&lt;/em&gt;.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In fact, &lt;code&gt;char(n)&lt;/code&gt; will use up more storage compared to the other two for strings with less than N characters because of padding. Both &lt;code&gt;char(n)&lt;/code&gt; and &lt;code&gt;varchar(n)&lt;/code&gt; incur an additional CPU cost to check the length, which might be unnecessary if you don't need it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Enforcing a maximum length&lt;/strong&gt;&lt;br&gt;
If you want to enforce a maximum length, it's better to use a &lt;a href="https://www.postgresql.org/docs/current/ddl-constraints.html#DDL-CONSTRAINTS-CHECK-CONSTRAINTS" rel="noopener noreferrer"&gt;check constraint&lt;/a&gt; instead of relying on &lt;code&gt;char(n)&lt;/code&gt; or &lt;code&gt;varchar(n)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Not only is a check constraint more &lt;em&gt;specific&lt;/em&gt;, but it will also save you from future trouble when you decide to change the length limit.&lt;/p&gt;

&lt;p&gt;Changing the &lt;code&gt;char(n)&lt;/code&gt; or &lt;code&gt;varchar(n)&lt;/code&gt; length limit practically means changing the column's data type and therefore it impacts dependent objects (views, functions, foreign keys, etc.). It could result in an expensive query due to a potential rewrite of the table during which other queries are put on hold.&lt;/p&gt;

&lt;p&gt;Modifying or dropping a check constraint is a quick operation that only involves reading the table's data. It's also more powerful and allows you to enforce other requirements such as a minimum (or exact) length and a limited set of characters.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="cm"&gt;/*
  Add a check constraint to the `id` column to enforce
  alphanumeric strings of exactly 5 characters long
*/&lt;/span&gt;
&lt;span class="k"&gt;ALTER&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;short_urls&lt;/span&gt; &lt;span class="k"&gt;ADD&lt;/span&gt; &lt;span class="k"&gt;CONSTRAINT&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="k"&gt;CHECK&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;~&lt;/span&gt; &lt;span class="s1"&gt;'^[a-zA-Z0-9]{5}$'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Always use the &lt;code&gt;text&lt;/code&gt; data type when storing strings in PostgreSQL. There is no performance benefit of using &lt;code&gt;char(n)&lt;/code&gt; or &lt;code&gt;varchar(n)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If you want to enforce a maximum length, use a check constraint which is more specific and easier to change.&lt;/p&gt;

&lt;p&gt;With this knowledge in hand, you can confidently move forward with designing and deploying your database.&lt;/p&gt;

&lt;h2&gt;
  
  
  Write clean code. Stay ahead of the curve.
&lt;/h2&gt;

&lt;p&gt;Every other Tuesday, I share tips on how to build robust Node.js applications. Join a community of developers committed to advancing their careers and gain the knowledge &amp;amp; skills you need to succeed. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://maximorlov.kit.com/0076aaf499" class="ltag_cta ltag_cta--branded" rel="noopener noreferrer"&gt;Subscribe for success!&lt;/a&gt;
&lt;/p&gt;

</description>
      <category>tooling</category>
      <category>opensource</category>
      <category>api</category>
      <category>github</category>
    </item>
    <item>
      <title>7 Awesome Free APIs for Your Next Node.js Project</title>
      <dc:creator>Maxim Orlov</dc:creator>
      <pubDate>Mon, 30 Jan 2023 05:48:09 +0000</pubDate>
      <link>https://dev.to/maximization/7-awesome-free-apis-for-your-next-nodejs-project-41m1</link>
      <guid>https://dev.to/maximization/7-awesome-free-apis-for-your-next-nodejs-project-41m1</guid>
      <description>&lt;p&gt;&lt;em&gt;This article was originally published at &lt;a href="https://maximorlov.com/awesome-apis-for-nodejs-projects/"&gt;https://maximorlov.com/awesome-apis-for-nodejs-projects/&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Coming up with an idea for your next portfolio project is not easy. The project should be: fun, not too difficult, and not too easy, impress recruiters, look nice on your portfolio, cover every aspect of Node.js you want to practice, etc., etc.&lt;/p&gt;

&lt;p&gt;You can't come up with something that fits all the criteria and you keep going in circles. &lt;strong&gt;You're &lt;em&gt;stuck&lt;/em&gt; in analysis paralysis.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Truth is, you're &lt;em&gt;way&lt;/em&gt; overthinking this.&lt;/p&gt;

&lt;p&gt;The type of project you decide to build &lt;em&gt;doesn't matter&lt;/em&gt; as much as you think it does. Whether it's a chatbot, a time tracker, or a fitness app, these are all solid choices.&lt;/p&gt;

&lt;p&gt;What truly matters is &lt;strong&gt;getting practice under your belt&lt;/strong&gt;, and every hour you spend fretting about making the right choice is a &lt;em&gt;lost&lt;/em&gt; hour you could've spent coding instead!&lt;/p&gt;

&lt;p&gt;To help you finally make a decision and start coding &lt;em&gt;today&lt;/em&gt;, I've put together &lt;strong&gt;a list of awesome free APIs&lt;/strong&gt;. You can use any of these APIs to build some really cool portfolio projects with Node.js, and for each API I'll give you some project ideas to get you inspired.&lt;/p&gt;

&lt;h2&gt;
  
  
  Spoonacular API 🥘
&lt;/h2&gt;

&lt;p&gt;Documentation: &lt;a href="https://spoonacular.com/food-api/docs"&gt;https://spoonacular.com/food-api/docs&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Spoonacular API is an API for all things related to food. It's a database for recipes, ingredients, nutritional data, wines, and more. With this vast amount of data, the project ideas are endless.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What can you build with it?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Wine purchase recommendation based on what the user is having for dinner&lt;/li&gt;
&lt;li&gt;A recipe suggestion app based on the user's food preferences and dietary requirements&lt;/li&gt;
&lt;li&gt;Image classification app for food (Improved version of the &lt;a href="https://www.youtube.com/watch?v=tWwCK95X6go"&gt;Not Hotdog App&lt;/a&gt; 😄)&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Do you want to have an attractive portfolio? Would you rather focus on the back end instead of fiddling with CSS?&lt;/strong&gt; &lt;a href="https://maximorlov.com/backend-portfolio-projects-no-css/"&gt;&lt;strong&gt;Learn more →&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Words API 💬
&lt;/h2&gt;

&lt;p&gt;Documentation: &lt;a href="https://www.wordsapi.com/docs/"&gt;https://www.wordsapi.com/docs/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Words API has over 350,000 English words in its database. The API has endpoints for word definitions, synonyms, and sentence examples. There is also a search endpoint that accepts regular expressions and min/max letter counts.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What can you build with it?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A word finder app for Scrabble. The user inputs the available tiles, including any wildcards, and the app suggests a list of possible words sorted by longest (and highest scoring) first&lt;/li&gt;
&lt;li&gt;Dictionary app that allows users to look up word definitions along with their pronunciation and class (noun, verb, adjective, etc.)&lt;/li&gt;
&lt;li&gt;A better writing app that lets the user paste some text and it suggests synonyms for frequently used words in the English language&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  AirLabs API ✈️
&lt;/h2&gt;

&lt;p&gt;Documentation: &lt;a href="https://airlabs.co/docs/flights"&gt;https://airlabs.co/docs/flights&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The AirLabs API provides you with real-time flight tracking data similar to flight radar sites. It gives you access to the live coordinates of any flight in the world.&lt;/p&gt;

&lt;p&gt;You can also give it a bounding box of coordinates and it will return all flights in a specific area. Pretty sweet!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What can you build with it?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;An app where users can track the flight of a friend or a loved one. Users can choose to get notified (push, sms, or email) when the airplane crosses borders, along with ETA, and when it lands&lt;/li&gt;
&lt;li&gt;A flight radar clone where users can see all airplanes in a specific area on the map. Users can click on an airplane to get more info about the flight (origin, destination, speed, etc.)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Bionic Reading API 📖
&lt;/h2&gt;

&lt;p&gt;Documentation: &lt;a href="https://rapidapi.com/bionic-reading-bionic-reading-default/api/bionic-reading1"&gt;https://rapidapi.com/bionic-reading-bionic-reading-default/api/bionic-reading1&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This API is different from the others in this list. Instead of giving you some data, you give the Bionic Reading API a text piece and it returns it with the beginning of the words highlighted.&lt;/p&gt;

&lt;p&gt;The idea is that if your eyes focus on the beginning of the words, your brain will automatically fill in the rest. Because we read faster with our minds than with our eyes, it improves reading speed and understanding of written content.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What can you build with it?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A blog with a toggle button where readers can choose to view blog posts with or without highlighted initial letters&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Open Library API 📚
&lt;/h2&gt;

&lt;p&gt;Documentation: &lt;a href="https://openlibrary.org/developers/api"&gt;https://openlibrary.org/developers/api&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Open Library API has pretty much every book ever released in its catalog. You can search for books or get detailed information on a particular book. The API has links to cover images and an array of genres for each book.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What can you build with it?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A GoodReads clone where users can keep track of the books they've read, and the ones they wish to read. Additionally, users can review books they've read&lt;/li&gt;
&lt;li&gt;A Book Club app where users can vote and pick what books to read. The app can recommend new books based on previously read books. Users can update their reading status and other users can see how far in the book everyone is&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Movie Database API 🍿
&lt;/h2&gt;

&lt;p&gt;Documentation: &lt;a href="https://developers.themoviedb.org/3/getting-started/introduction"&gt;https://developers.themoviedb.org/3/getting-started/introduction&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There's a good reason every project ideas list like this one mentions a movie API. Everyone watches movies or TV shows and therefore it's likely to be an interesting project idea.&lt;/p&gt;

&lt;p&gt;The Movie Database has most of the movies and TV shows that have ever been released. The API gives you access to a variety of useful information for each movie/TV show such as genre, rating, and actors. It also provides you with cover images so you can make your project visually attractive.&lt;/p&gt;

&lt;p&gt;The API has a trending, a discovery, and a recommendation endpoint which opens the door for some interesting projects.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What can you build with it?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A "Where Can I Stream It?" app that lets the user know on which streaming service to watch a particular movie or TV show based on their country&lt;/li&gt;
&lt;li&gt;A movie library where users can keep track of the movies and TV shows they've watched, and the ones they wish to watch. Users can rate movies and a recommendation engine will take that into account to suggest other movies to watch&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  API Ninjas' Exercises API 🏋️‍♂️
&lt;/h2&gt;

&lt;p&gt;Documentation: &lt;a href="https://api-ninjas.com/api/exercises"&gt;https://api-ninjas.com/api/exercises&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Exercises API is a collection of thousands of exercises. You can filter exercises by the muscle group targeted, type and difficulty. Each exercise includes an instruction text on how to perform the exercise and the necessary equipment for it if any.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What can you build with it?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A fitness inspiration app where users can search for and browse exercises with filters for targeted muscles, difficulty, and type. The app can also suggest a weekly training program based on the user's level, muscle focus preference, and available training equipment&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You should now have plenty of inspiration for your next Node.js portfolio project. You have no excuse to procrastinate any longer. Choose one of these APIs and an idea that seems fun to you and go build something awesome. 🌟&lt;/p&gt;

&lt;p&gt;Remember, choosing &lt;em&gt;something&lt;/em&gt; is better than &lt;em&gt;not choosing&lt;/em&gt; at all!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Do you want to have an attractive portfolio? Would you rather focus on the back end instead of fiddling with CSS?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I'm releasing a collection of portfolio projects that include a beautiful and complete front end. &lt;a href="https://maximorlov.com/backend-portfolio-projects-no-css/"&gt;&lt;strong&gt;Learn more →&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>beginners</category>
      <category>codenewbie</category>
      <category>career</category>
      <category>api</category>
    </item>
    <item>
      <title>Backend Portfolio Projects for Developers Who Dread CSS</title>
      <dc:creator>Maxim Orlov</dc:creator>
      <pubDate>Fri, 20 Jan 2023 06:01:19 +0000</pubDate>
      <link>https://dev.to/maximization/backend-portfolio-projects-for-developers-who-dread-css-1mbn</link>
      <guid>https://dev.to/maximization/backend-portfolio-projects-for-developers-who-dread-css-1mbn</guid>
      <description>&lt;p&gt;&lt;em&gt;This article was originally published at &lt;a href="https://maximorlov.com/backend-portfolio-projects-no-css/" rel="noopener noreferrer"&gt;https://maximorlov.com/backend-portfolio-projects-no-css/&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Having a portfolio is &lt;em&gt;essential&lt;/em&gt; to landing a web development job. As a back-end developer, how do you &lt;em&gt;showcase&lt;/em&gt; your skills when most of it happens, well, in the back end?!&lt;/p&gt;

&lt;p&gt;You might use Postman to send requests to your server, but you can't expect recruiters to do that. They need an easy and quick way to &lt;em&gt;see&lt;/em&gt; what you've built. You need a &lt;em&gt;front end&lt;/em&gt; to accompany your back end.&lt;/p&gt;

&lt;p&gt;You need &lt;strong&gt;HTML&lt;/strong&gt; and &lt;strong&gt;CSS&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;But writing CSS isn't your forte. In fact, you could easily spend &lt;em&gt;hours&lt;/em&gt; fiddling with CSS only to end up with a page that looks like it was built in the 90s.&lt;/p&gt;

&lt;p&gt;Imagine showing one of your projects to a recruiter while trying to convince them the back end is really well done and they should &lt;strong&gt;ignore the design..&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That's awkward.&lt;/p&gt;

&lt;p&gt;Despite having the design skills of a 5-year-old, your projects &lt;em&gt;don't have to&lt;/em&gt; reflect that.&lt;/p&gt;

&lt;p&gt;What if you had a portfolio you were &lt;em&gt;truly&lt;/em&gt; proud of? A portfolio of beautifully designed projects that are worthy of your intelligently written back ends.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A portfolio worthy of YOU.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This portfolio would make you &lt;strong&gt;stand out&lt;/strong&gt; from all other candidates. It would get you past the screening stage and sitting at a table in front of your future employer.&lt;/p&gt;

&lt;p&gt;Best of all, what if you accomplished all of that without writing even &lt;em&gt;a single line&lt;/em&gt; of CSS? Wouldn't it be great if you spent your time writing back-end logic instead — the type of coding you're &lt;em&gt;actually&lt;/em&gt; good at.&lt;/p&gt;

&lt;p&gt;Well, now you can!&lt;/p&gt;

&lt;h2&gt;
  
  
  Introducing back-end projects packaged with a front-end application
&lt;/h2&gt;

&lt;p&gt;I'm releasing a collection of portfolio projects that come with an already &lt;strong&gt;built front-end application&lt;/strong&gt; so you can focus &lt;em&gt;entirely&lt;/em&gt; on the back end.&lt;/p&gt;

&lt;p&gt;These projects will cover a wide range of back-end topics such as authentication, caching, sockets and security, making them an ideal choice for &lt;strong&gt;learning and practicing Node.js&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;By the time you complete several of these projects, you'll have a &lt;em&gt;strong&lt;/em&gt; portfolio showcasing your web development skills.&lt;/p&gt;

&lt;p&gt;Want to use Express, Fastify, Nest.js, or any other back-end framework? Not a problem! SQL or NoSQL? Up to you! There are absolutely &lt;em&gt;no restrictions&lt;/em&gt; on how you should build these projects.&lt;/p&gt;

&lt;p&gt;You're free to choose &lt;em&gt;any&lt;/em&gt; frameworks and libraries you want. This is an excellent opportunity to try out a new library or learn a technology that will give you an edge on the job market.&lt;/p&gt;

&lt;h2&gt;
  
  
  URL Shortener project
&lt;/h2&gt;

&lt;p&gt;The first project in the series is a &lt;strong&gt;URL Shortener&lt;/strong&gt; service.&lt;/p&gt;

&lt;p&gt;Your task is to implement a back-end that enables users to shorten a long URL. The short URL should redirect visitors to the original URL when visited. Additionally, users should be able to view the number of times an URL has been visited.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I'm giving the first project away for FREE. &lt;a href="https://maximorlov.com/backend-portfolio-projects-no-css/" rel="noopener noreferrer"&gt;&lt;strong&gt;Learn more →&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  What's inside
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Front-end application
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3mv8qat5c7h063ywl9ow.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3mv8qat5c7h063ywl9ow.png" alt="Application screenshots of the home, short URL and analytics page on mobile."&gt;&lt;/a&gt;&lt;/p&gt;
Screenshots of the Home, Short URL and Analytics mobile pages



&lt;p&gt;Each project comes with a fully designed and implemented front-end application. It's a plug-and-play application ready to connect to a back end. Just give it a URL and you're good to go.&lt;/p&gt;

&lt;h3&gt;
  
  
  API Documentation
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw6wu1pf70fpcfymiww9o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw6wu1pf70fpcfymiww9o.png" alt="API Documentation for URL Shortener project documenting three endpoints: Create a short URL, Get a short URL and Visit a short URL."&gt;&lt;/a&gt;&lt;/p&gt;
API documentation for the endpoint to create a short URL



&lt;p&gt;Back-end developers often use the API documentation to coordinate with front-end developers. API documentation is a formalized document of how the client and server will communicate.&lt;/p&gt;

&lt;p&gt;Typical API documentation will describe how the client should authenticate with the server, what the available endpoints are, and what the data returned by the back end looks like.&lt;/p&gt;

&lt;p&gt;As a back-end developer, you should be comfortable with implementing a back end that closely matches the documentation. API documentation is to back-end developers, what design files are to front-end developers.&lt;/p&gt;

&lt;h3&gt;
  
  
  User stories
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyozd8f7xdgrtfwdcqhzo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyozd8f7xdgrtfwdcqhzo.png" alt="User Stories for URL Shortener project: 1. As a user, I want to submit an URL and receive a short URL in return, 2. As a user, when I navigate to the short URL I want to be redirected to the original URL, 3. As a user, navigating to the short URL should increase the visit count by 1, 4. As a user, I want to submit a short URL and see how many times it has been visited, 5. As a user, when I navigate to a non-existing short URL I should see a page informing the URL doesn\'t exist."&gt;&lt;/a&gt;&lt;/p&gt;
Essential features of the URL Shortener project



&lt;p&gt;User stories provide an overview of the features you will be implementing. They give you a good idea of what the project is about.&lt;/p&gt;

&lt;p&gt;These are a collection of essential features written from the user's perspective. User stories encourage backward planning by starting with the end result first. Use them to work your way backward and decompose the project into many small tasks.&lt;/p&gt;

&lt;p&gt;Together with the API documentation, user stories are a great starting point for integration tests.&lt;/p&gt;

&lt;h3&gt;
  
  
  Bonus tasks
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F62myh3qgghtzanj9m27f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F62myh3qgghtzanj9m27f.png" alt="Bonus tasks for the URL Shortener project: 1. Short URLs should not be easy to guess, 2. Submitting the same URL more than once should return its corresponding short URL instead of creating a new short URL, 3. Check if a URL is already a short URL to avoid shortening a short URL, 4. Check if the URL leads to a valid page before shortening it, 5. Make it harder to shorten URLs that lead to known malicious sites (short URLs are often used by scammers)."&gt;&lt;/a&gt;&lt;/p&gt;
Bonus tasks add an extra level of difficulty



&lt;p&gt;For ambitious developers who like an extra challenge, each project comes with additional bonus tasks. These tasks go beyond the initial scope of the project and challenge your problem-solving skills.&lt;/p&gt;

&lt;p&gt;If the user stories are the Minimum Viable Product (MVP), bonus tasks are the polished version of a product. Completing the bonus tasks shows you're capable of analyzing, researching, and solving real-world problems.&lt;/p&gt;

&lt;p&gt;Don't feel the pressure to finish all, or any, bonus tasks. If you implement just the essential features that's already a big accomplishment.&lt;/p&gt;

&lt;h3&gt;
  
  
  Resources
&lt;/h3&gt;

&lt;p&gt;Resources are various links to tutorials, Stack Overflow questions, Wikipedia pages, or blog posts that can help you with the project. If you get stuck building the project, these resources can help you get unstuck and learn a different problem-solving approach.&lt;/p&gt;

&lt;p&gt;These resources work best when used as inspiration. Try not to copy-paste code from them and if you absolutely have to, make sure you fully understand what each line of code does.&lt;/p&gt;

&lt;h3&gt;
  
  
  Additional support
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;A workflow for building the project.&lt;/strong&gt; This is a step-by-step workflow on how I would build the project. From initializing a GitHub repository to implementing a mock server to connecting a database. These are a sequence of steps. Feel free to adapt it to your liking or use your own workflow.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Deployment tips.&lt;/strong&gt; How you deploy the back end will largely depend on whether you want to host it on a server (VPS) or a managed server (PaaS). With the plethora of cloud providers today, I lay out the options available to you along with some recommendations that have free tiers.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;For a limited time only, I'm offering FREE &lt;strong&gt;professional code reviews&lt;/strong&gt; for anyone who completes a project! Don't miss this unique opportunity to get actionable personalized feedback on your code.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Go build something awesome!
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://maximorlov.com/backend-portfolio-projects-no-css/" rel="noopener noreferrer"&gt;&lt;strong&gt;Visit the original article&lt;/strong&gt;&lt;/a&gt; and download the project files to get started.&lt;/p&gt;

&lt;p&gt;I'm super excited to see the awesome stuff you'll make and I'm curious to see what approach you'll take to solve these projects.&lt;/p&gt;

&lt;p&gt;I'd love to have a look at your solution. &lt;a href="//mailto:hello@maximorlov.com"&gt;Shoot me an email&lt;/a&gt; with a link or &lt;a href="https://twitter.com/_maximization" rel="noopener noreferrer"&gt;mention me on Twitter&lt;/a&gt;. I'll help spread the word!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Have fun building! ⚒️&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>javascript</category>
      <category>webdev</category>
      <category>node</category>
    </item>
    <item>
      <title>3 Reasons Why Async/Await Is Better Than Chaining Promises</title>
      <dc:creator>Maxim Orlov</dc:creator>
      <pubDate>Wed, 02 Nov 2022 14:00:00 +0000</pubDate>
      <link>https://dev.to/maximization/3-reasons-why-asyncawait-is-better-than-chaining-promises-hk1</link>
      <guid>https://dev.to/maximization/3-reasons-why-asyncawait-is-better-than-chaining-promises-hk1</guid>
      <description>&lt;p&gt;&lt;em&gt;This article was originally published at &lt;a href="https://maximorlov.com/async-await-better-than-chaining-promises/" rel="noopener noreferrer"&gt;https://maximorlov.com/async-await-better-than-chaining-promises/&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;If you're already familiar with promises and chaining them you might be wondering — why learn a new syntax? Why use async/await when you can use promises to accomplish the same thing? 🤨&lt;/p&gt;

&lt;p&gt;And yet developers &lt;em&gt;love&lt;/em&gt; async/await and are saying how it has helped them write better code. Makes you wonder if they know something you don't...&lt;/p&gt;

&lt;p&gt;Only if you had someone to show you where promises fall short. It could &lt;strong&gt;give you the insight you've been missing&lt;/strong&gt; all this time! 💡&lt;/p&gt;

&lt;p&gt;Well, you do!&lt;/p&gt;

&lt;p&gt;Grab a seat and read on as I point out the shortcomings of Promise.then() syntax and how async/await helps you write better asynchronous JavaScript code. 🎯&lt;/p&gt;

&lt;h2&gt;
  
  
  Reason #1 - Confusing order of execution
&lt;/h2&gt;

&lt;p&gt;One of the first things we're taught in programming is that code is executed from top to bottom. We tell machines what to do by writing code as a sequence of chronological steps — first do this, then do that, and finally run that.&lt;/p&gt;

&lt;p&gt;By definition, asynchronous code &lt;em&gt;doesn't&lt;/em&gt; run linearly and it &lt;strong&gt;contradicts how we've learned to read and reason about code&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;While promises are a vast improvement over callbacks (and they &lt;a href="https://maximorlov.com/understanding-async-await/" rel="noopener noreferrer"&gt;power async/await under the hood&lt;/a&gt;), they can give you the impression that code runs in a weird order.&lt;/p&gt;

&lt;p&gt;Here is an example with print statements before, inside, and after the promise chain:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Start&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 1&lt;/span&gt;
&lt;span class="nf"&gt;insertComment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;comment&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;commentId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Comment ID is&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;commentId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 3&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;End&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This prints the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Start
End
Comment ID is e03c2055-2309-494f-b37e-f153bc673445
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is unintuitive because it looks like the program is jumping from end to middle, when in fact code always executes from top to bottom. What happens is that the execution of asynchronous code is deferred to a future point in time with the help of &lt;a href="https://maximorlov.com/javascript-event-loop-talk/" rel="noopener noreferrer"&gt;the event loop&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;When we take the same code and &lt;a href="https://maximorlov.com/visual-guide-refactoring-callback-functions/" rel="noopener noreferrer"&gt;refactor it to async/await&lt;/a&gt;, it not only runs from top to bottom but also &lt;em&gt;reads&lt;/em&gt; from top to bottom.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Start&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 1&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;commentId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;insertComment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;comment&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Comment ID is&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;commentId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 2&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;End&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Which unsurprisingly prints:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Start
Comment ID is e03c2055-2309-494f-b37e-f153bc673445
End
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Async/await allows you to write asynchronous code that reads like synchronous code.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;And that's powerful.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reason #2 - Reusing values inside promise chains
&lt;/h2&gt;

&lt;p&gt;Another issue with promise chains is when you want to reuse values at later steps in the chain. Each &lt;code&gt;.then()&lt;/code&gt; method creates a separate function scope and, therefore, prevents accessing its variables from later steps in the chain.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;insertComment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;comment&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;commentId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;insertHashtag&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;hashtag&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;commentId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;hashtagId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// how do we use commentId in here?&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Comment ID is&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;commentId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In practice, this issue is often worse because you have longer promise chains and you want to access several values at different steps in the chain.&lt;/p&gt;

&lt;h3&gt;
  
  
  Promise.then() solutions and their shortcomings
&lt;/h3&gt;

&lt;p&gt;You could solve this in a few different ways with Promise.then() syntax, but let me show you why they're not ideal.&lt;/p&gt;

&lt;p&gt;A solution would be to initialize the variables you need outside of the promise chain. This allows you to reference them at later steps in the chain because the variables are declared in a shared outer scope.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Initialize variable in outer scope so we can reference it&lt;/span&gt;
&lt;span class="c1"&gt;// from a later step in the promise chain&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;commentId&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nf"&gt;insertComment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;comment&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;newCommentId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Need to come up with a new name to avoid name clash 🙅‍♂️&lt;/span&gt;
    &lt;span class="nx"&gt;commentId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;newCommentId&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;insertHashtag&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;hashtag&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;commentId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;hashtagId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Comment ID is&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;commentId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The problem with this is that you have to come up with different names for each variable to avoid name clashes, and we all know that naming things is hard in programming.&lt;/p&gt;

&lt;p&gt;Moreover, with longer promise chains it's hard to keep track of where the variables were assigned and what values they hold. I've had to debug some long promise chains in production that were using this solution and I can tell you it was &lt;em&gt;not fun&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Another solution is to add a nested promise chain and resolve with the value needed in the next step.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;insertComment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;comment&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;commentId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;insertHashtag&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;hashtag&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;commentId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="c1"&gt;// Add a nested promise chain and resolve with the value&lt;/span&gt;
      &lt;span class="c1"&gt;// needed in the next step&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;hashtagId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;commentId&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// this nesting though 😵&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;commentId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Comment ID is&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;commentId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, nesting promise chains goes against why you would chain promises in the first place — which is to create a flat async structure. Everyone hated callback hell (a.k.a. pyramid of doom) from earlier days of asynchronous JavaScript, and nobody wants to work with that mess again.&lt;/p&gt;

&lt;p&gt;You also need to make sure to return nested promises otherwise rejections won't bubble up and &lt;a href="https://maximorlov.com/node-js-15-is-out-what-does-it-mean-for-you/#unhandled-rejections-are-thrown" rel="noopener noreferrer"&gt;your Node.js server will quit unexpectedly&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Lastly, you could use &lt;code&gt;Promise.all&lt;/code&gt; to pass an array of values to subsequent steps in the chain.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;insertComment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;comment&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;commentId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Need to make sure to keep this array in sync with..&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
      &lt;span class="nx"&gt;commentId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nf"&gt;insertHashtag&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;hashtag&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;commentId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;]);&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(([&lt;/span&gt;&lt;span class="nx"&gt;commentId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;hashtagId&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// &amp;lt;-- ..this array&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Comment ID is&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;commentId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is in my opinion the "least worse" solution, as it avoids name clashes or nesting promises. Before async/await was a thing, this would be my go-to approach.&lt;/p&gt;

&lt;p&gt;The downside is that you have to keep both arrays in sync. When you change something in one array it's easy to forget about the other. Adding Promise.all in your promise chains quickly becomes tedious and it affects the readability of your code.&lt;/p&gt;

&lt;h3&gt;
  
  
  Using async/await
&lt;/h3&gt;

&lt;p&gt;Let's look at how you'd write this with async/await.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ✨&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;commentId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;insertComment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;comment&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;insertHashtag&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;hashtag&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;commentId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Comment ID is&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;commentId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There's not much to explain really, it's concise and clear. No separate function scopes to worry about and no weird workarounds. Amazing!&lt;/p&gt;

&lt;h2&gt;
  
  
  Reason #3 - Conditional asynchronous tasks
&lt;/h2&gt;

&lt;p&gt;Another reason to use async/await over Promise.then() syntax is when you have async tasks inside an if statement. It's tricky to handle this nicely with Promise.then() and you'll soon find yourself in a "promise hell".&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;insertComment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;comment&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;commentId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;hashtag&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// Ugh this nesting starts to look like callback hell...&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;insertHashtag&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;hashtag&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;commentId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;hashtagId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="c1"&gt;// If we don't resolve with commentId the next value&lt;/span&gt;
          &lt;span class="c1"&gt;// in the chain might be hashtagId and we'll have&lt;/span&gt;
          &lt;span class="c1"&gt;// to add a check for that&lt;/span&gt;
          &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;commentId&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;commentId&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;commentId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Comment ID is&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;commentId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can't get around the nesting problem because if you resolve with a different value (hashtagId) you won't know what value you're getting in the next step (hashtagId or commentId?). In some situations you can programmatically check which value you're working with, but often you can't.&lt;/p&gt;

&lt;p&gt;With async/await this is a non-issue. You just put the entire logic inside an if statement and that's it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// 🚀&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;commentId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;insertComment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;comment&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;hashtag&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;insertHashtag&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;hashtag&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;commentId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Comment ID is&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;commentId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code is straightforward and runs as expected.&lt;/p&gt;

&lt;p&gt;By now you're familiar with the scenarios where Promise.then() syntax falls short and how async/await empowers you to write clean asynchronous code. Use this knowledge to write better JavaScript code and progress in your development career.&lt;/p&gt;

&lt;h2&gt;
  
  
  Transform Callbacks into Clean Async Code! 🚀
&lt;/h2&gt;

&lt;p&gt;Tired of messy callback code? Download this &lt;strong&gt;FREE 5-step guide&lt;/strong&gt; to master async/await and simplify your asynchronous code.&lt;/p&gt;

&lt;p&gt;In just a few steps, you'll transform complex logic into readable, &lt;em&gt;modern JavaScript&lt;/em&gt; that's easy to maintain. With clear visuals, each step breaks down the process so you can follow along effortlessly.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkuh49fp3fcc0hs1axenb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkuh49fp3fcc0hs1axenb.png" alt="Refactoring Callbacks Guide Preview" width="800" height="494"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://pages.maximorlov.com/refactoring-callbacks-guide" class="ltag_cta ltag_cta--branded" rel="noopener noreferrer"&gt;Get the FREE guide&lt;/a&gt;
&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>beginners</category>
      <category>webdev</category>
      <category>programming</category>
    </item>
    <item>
      <title>Using Callbacks With Async/Await</title>
      <dc:creator>Maxim Orlov</dc:creator>
      <pubDate>Mon, 24 Oct 2022 10:24:20 +0000</pubDate>
      <link>https://dev.to/maximization/using-callbacks-with-asyncawait-2od9</link>
      <guid>https://dev.to/maximization/using-callbacks-with-asyncawait-2od9</guid>
      <description>&lt;p&gt;&lt;em&gt;This article was originally published at &lt;a href="https://maximorlov.com/using-callbacks-with-async-await/" rel="noopener noreferrer"&gt;https://maximorlov.com/using-callbacks-with-async-await/&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Let's face it. Sometimes you have to use an asynchronous function that uses the old callback-based approach. It might be part of a legacy codebase, or it could come from a library that hasn't had an update in over 5 years. 🤷‍♂️&lt;/p&gt;

&lt;p&gt;Nevertheless, there's no way around it and you have to deal with it somehow.&lt;/p&gt;

&lt;p&gt;So what do you do? Do you add messy callbacks to your code? 🙅‍♂️&lt;/p&gt;

&lt;p&gt;What if I told you there is a way to &lt;strong&gt;make callback-based asynchronous functions work nicely with async/await?&lt;/strong&gt; Not only that, but you won't have to make &lt;em&gt;any&lt;/em&gt; changes to existing code.&lt;/p&gt;

&lt;p&gt;I'll teach you how to change a function's signature, even when you don't have control over its implementation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Transforming callback-based asynchronous functions
&lt;/h2&gt;

&lt;p&gt;Suppose we have a &lt;code&gt;getUserAddress&lt;/code&gt; function that's written using modern async/await. Inside this function, we're calling &lt;code&gt;fetchUser&lt;/code&gt; which uses a callback-based approach.&lt;/p&gt;

&lt;p&gt;When &lt;code&gt;fetchUser&lt;/code&gt; completes, it calls the callback with the user object. Our goal is to have &lt;code&gt;getUserAddress&lt;/code&gt; return the user's address.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getUserAddress&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;fetchUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// we want this value&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;address&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;getUserAddress&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// to be returned here&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// undefined&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;How do we accomplish that?&lt;/p&gt;

&lt;p&gt;We can't simply return &lt;code&gt;user.address&lt;/code&gt; inside the callback function because the return value would go to the parent function that calls the callback, which is the &lt;code&gt;fetchUser&lt;/code&gt; function and &lt;em&gt;not&lt;/em&gt; &lt;code&gt;getUserAddress&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getUserAddress&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;fetchUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// 🚫 doesn't work, value is returned to fetchUser function&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;address&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;getUserAddress&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// undefined&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And returning &lt;code&gt;fetchUser&lt;/code&gt; doesn't work either because by design the function doesn't return anything. In fact, &lt;strong&gt;all callback-based asynchronous functions return undefined&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getUserAddress&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// 🚫 doesn't work, fetchUser doesn't return anything&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;fetchUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;address&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;getUserAddress&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// undefined&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Well then, the only way to use &lt;code&gt;fetchUser&lt;/code&gt; with async/await is if the function returns a Promise. &lt;strong&gt;Callback-based functions are incompatible with promises &amp;amp; async/await&lt;/strong&gt; because they are different approaches to writing asynchronous code.&lt;/p&gt;

&lt;p&gt;But how do we make &lt;code&gt;fetchUser&lt;/code&gt; return a Promise when we don't have control over its implementation?&lt;/p&gt;

&lt;p&gt;We wrap it! 🌯&lt;/p&gt;

&lt;p&gt;If we wrap &lt;code&gt;fetchUser&lt;/code&gt; inside a promise that resolves with the user value and rejects with the error object, we can await the promise and return the user's address inside &lt;code&gt;getUserAddress&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getUserAddress&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Create and await a promise that rejects and resolves&lt;/span&gt;
  &lt;span class="c1"&gt;// with the callback's `err` and `user` arguments, respectively&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;fetchUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nf"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
          &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;address&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;getUserAddress&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// '729 Ellsworth Summit, Aliyaview'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What this does is it creates a bridge between the asynchronous callback and async/await. It translates the success and error paths inside the callback to the resolve and rejection states of the promise.&lt;/p&gt;

&lt;p&gt;When the callback is called with an &lt;code&gt;err&lt;/code&gt; argument the promise will reject with the error object which is then caught and logged in the catch block. If there is no error, the promise resolves with the user which is assigned to a variable.&lt;/p&gt;

&lt;p&gt;Finally, we call &lt;code&gt;getUserAddress&lt;/code&gt; which returns a promise, &lt;a href="https://maximorlov.com/understanding-async-await/" rel="noopener noreferrer"&gt;because all async functions return a promise&lt;/a&gt;, and await it to get the user's address.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using a utility function
&lt;/h2&gt;

&lt;p&gt;It quickly becomes tedious if you have to manually wrap all callback-based functions in your project. Luckily, Node.js comes with a utility function that does this for you.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;promisify&lt;/code&gt; method from the built-in &lt;code&gt;util&lt;/code&gt; module takes a callback-based asynchronous function and returns a promise-based version. You call the promise-based function with the same parameters as you would call the callback-based function, except instead of passing in a callback you await the promise for the resolved value.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;util&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;node:util&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;fetchUser&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../utils/api.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// util.promisify transforms a callback-based function&lt;/span&gt;
&lt;span class="c1"&gt;// into a promise-based equivalent&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fetchUserAsync&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;util&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;promisify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fetchUser&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getUserAddress&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetchUserAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;address&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;getUserAddress&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// '729 Ellsworth Summit, Aliyaview'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is much better than what we've started with, and it works! 🎉&lt;/p&gt;

&lt;p&gt;You've learned how to transform a callback-based asynchronous function into a function that returns a promise despite not having control over its internal implementation. There's no need to write asynchronous JavaScript code using a callback-based approach anymore.&lt;/p&gt;

&lt;h2&gt;
  
  
  Transform Callbacks into Clean Async Code! 🚀
&lt;/h2&gt;

&lt;p&gt;Tired of messy callback code? Download this &lt;strong&gt;FREE 5-step guide&lt;/strong&gt; to master async/await and simplify your asynchronous code.&lt;/p&gt;

&lt;p&gt;In just a few steps, you'll transform complex logic into readable, &lt;em&gt;modern JavaScript&lt;/em&gt; that's easy to maintain. With clear visuals, each step breaks down the process so you can follow along effortlessly.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkuh49fp3fcc0hs1axenb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkuh49fp3fcc0hs1axenb.png" alt="Refactoring Callbacks Guide Preview" width="800" height="494"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://pages.maximorlov.com/refactoring-callbacks-guide" class="ltag_cta ltag_cta--branded" rel="noopener noreferrer"&gt;Get the FREE guide&lt;/a&gt;
&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>beginners</category>
      <category>webdev</category>
      <category>programming</category>
    </item>
    <item>
      <title>Avoid This Mistake When Caching Asynchronous Results</title>
      <dc:creator>Maxim Orlov</dc:creator>
      <pubDate>Mon, 17 Oct 2022 11:55:32 +0000</pubDate>
      <link>https://dev.to/maximization/avoid-this-mistake-when-caching-asynchronous-results-53jh</link>
      <guid>https://dev.to/maximization/avoid-this-mistake-when-caching-asynchronous-results-53jh</guid>
      <description>&lt;p&gt;&lt;em&gt;This article was originally published at &lt;a href="https://maximorlov.com/caching-asynchronous-results/" rel="noopener noreferrer"&gt;https://maximorlov.com/caching-asynchronous-results/&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Implementing a robust cache is a challenging task. Some of the things you'll need to consider are — What will you cache? When will you invalidate? And, what strategy will you implement? 🤔&lt;/p&gt;

&lt;p&gt;The primary job of a cache is to reduce load on upstream services. Therefore, &lt;strong&gt;last thing you want is an ineffective and useless cache.&lt;/strong&gt; 😤&lt;/p&gt;

&lt;p&gt;Unfortunately, this is something that happens all too often when caching asynchronous results.&lt;/p&gt;

&lt;p&gt;Here's what you should watch out for, and how you can implement a cache that guarantees no cache misses.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cache stampede
&lt;/h2&gt;

&lt;p&gt;In the context of web applications, a cache stampede occurs when several requests are fetching the same resource in parallel. If the resource is missing from the cache, each request ends up initiating a separate database query.&lt;/p&gt;

&lt;p&gt;To illustrate, suppose a query takes 3 seconds to complete and the incoming traffic is 10 requests per second (for the same resource). On a cache miss, we'll end up with 30 identical database queries before we start serving the resource from the cache!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjfn4jpk6djhujgu6pp47.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjfn4jpk6djhujgu6pp47.png" alt="Diagram showing multiple requests getting a cache miss and sending identical queries to the database." width="800" height="431"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The longer it takes for a query to complete and the higher the incoming traffic, the larger the load on the database. This can result in slow response times or even a complete outage. (&lt;a href="https://betterprogramming.pub/how-a-cache-stampede-caused-one-of-facebooks-biggest-outages-dbb964ffc8ed" rel="noopener noreferrer"&gt;looking at you, Facebook&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;The core of the problem is that &lt;strong&gt;requests aren't aware of each other&lt;/strong&gt;. They act independently which leads to duplicate work. Ideally, requests should know about one another and reuse pending work.&lt;/p&gt;

&lt;p&gt;One way to solve a cache stampede is to introduce a &lt;em&gt;locking mechanism&lt;/em&gt;. On a cache miss, a request tries to acquire a lock for a particular resource and recompute it only if it has acquired a lock.&lt;/p&gt;

&lt;h2&gt;
  
  
  Implement locks using promises
&lt;/h2&gt;

&lt;p&gt;An ingenious way of implementing a locking mechanism is to use promises. Instead of storing the value in the cache, we store the corresponding promise.&lt;/p&gt;

&lt;p&gt;We can make use of the fact that promises are created synchronously, whereas query results are returned asynchronously. This ensures that with multiple concurrent requests, only the &lt;em&gt;first&lt;/em&gt; request will propagate a query to the database. Subsequent requests will reuse the same promise and wait until it fulfills.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7gm7uc4umfx7cbaf3fkh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7gm7uc4umfx7cbaf3fkh.png" alt="Diagram showing multiple requests getting a cache miss but not sending identical queries to the database since the same promise is re-used." width="800" height="338"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's look at some code.&lt;/p&gt;

&lt;p&gt;Below, we have a &lt;code&gt;getUser&lt;/code&gt; function that takes a user ID and returns a promise that fulfills with the user object. The function first checks if there is a promise for that particular user ID in the cache. If there is, return the promise. If there isn't, initiate a query to get the user from the database and store the resulting promise in the cache before returning it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userPromiseCache&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// If the promise is not stored in the cache, fetch the user from DB&lt;/span&gt;
  &lt;span class="c1"&gt;// and store the resulting promise in the cache&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;userPromiseCache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;has&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userPromise&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findUserById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Have the promise remove itself from the cache if it rejects&lt;/span&gt;
        &lt;span class="nx"&gt;userPromiseCache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="c1"&gt;// Store promise in the cache&lt;/span&gt;
    &lt;span class="nx"&gt;userPromiseCache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;userPromise&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// Return the promise from cache&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;userPromiseCache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice the error handler attached to the promise. It ensures the promise will remove itself from the cache if it rejects. Otherwise, we'll end up caching the rejection and future requests will return an error. It's ok to use the &lt;code&gt;.catch()&lt;/code&gt; method here since there's no other way. Generally though, you want to &lt;a href="https://maximorlov.com/why-you-shouldnt-mix-promise-then-with-async-await/" rel="noopener noreferrer"&gt;avoid mixing Promise.then() with async/await syntax&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Because the promise is created and returned synchronously, &lt;strong&gt;subsequent calls with the same user ID are guaranteed to reuse the same promise&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Usually, a locking mechanism involves complex logic for lock acquisition. This technique gives you simple and straightforward locks.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: Promises are a language-specific construct and this technique works only for in-memory cache inside JavaScript code. For external cache storages like Redis, you'll need to manually &lt;a href="https://redis.com/blog/caches-promises-locks/" rel="noopener noreferrer"&gt;implement locking using a Pub/Sub pattern&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Memoizing promises
&lt;/h2&gt;

&lt;p&gt;Seen from another angle, this cache implementation is just memoizing the &lt;code&gt;getUser&lt;/code&gt; function. When we call the function with the same &lt;code&gt;userId&lt;/code&gt;, we get the same cached result (a promise).&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: Memoization is an optimization technique that stores the results of expensive function calls and returns the cached result when the same inputs occur again.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;There are several libraries in the JavaScript ecosystem that help with memoization, including &lt;code&gt;memoizee&lt;/code&gt;. We can simplify the above implementation to just:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;memoizee&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;memoizee&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getUser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;memoizee&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findUserById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;promise&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With &lt;code&gt;promise: true&lt;/code&gt; we let the library know that the function returns a promise. It will then make sure to remove promise rejections like we manually did earlier.&lt;/p&gt;

&lt;p&gt;Looks clean, doesn't it?! ✨&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: Make sure you have a cache eviction policy in place to avoid outgrowing your application's memory limits. In memoizee, you can limit the cache size with the &lt;code&gt;max&lt;/code&gt; property.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You have now learned the peril of caching asynchronous values and how to avoid it. With this knowledge in hand, you're ready to implement a robust cache with more cache hits!&lt;/p&gt;

&lt;h2&gt;
  
  
  Transform Callbacks into Clean Async Code! 🚀
&lt;/h2&gt;

&lt;p&gt;Tired of messy callback code? Download this &lt;strong&gt;FREE 5-step guide&lt;/strong&gt; to master async/await and simplify your asynchronous code.&lt;/p&gt;

&lt;p&gt;In just a few steps, you'll transform complex logic into readable, &lt;em&gt;modern JavaScript&lt;/em&gt; that's easy to maintain. With clear visuals, each step breaks down the process so you can follow along effortlessly.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkuh49fp3fcc0hs1axenb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkuh49fp3fcc0hs1axenb.png" alt="Refactoring Callbacks Guide Preview" width="800" height="494"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://pages.maximorlov.com/refactoring-callbacks-guide" class="ltag_cta ltag_cta--branded" rel="noopener noreferrer"&gt;Get the FREE guide&lt;/a&gt;
&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>programming</category>
      <category>node</category>
    </item>
    <item>
      <title>Understanding Async &amp; Await</title>
      <dc:creator>Maxim Orlov</dc:creator>
      <pubDate>Fri, 07 Oct 2022 12:28:25 +0000</pubDate>
      <link>https://dev.to/maximization/understanding-async-await-22o6</link>
      <guid>https://dev.to/maximization/understanding-async-await-22o6</guid>
      <description>&lt;p&gt;&lt;em&gt;This article was originally published at &lt;a href="https://maximorlov.com/understanding-async-await/" rel="noopener noreferrer"&gt;https://maximorlov.com/understanding-async-await/&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Learning async/await can be daunting. It's something you've been procrastinating on for weeks, if not months!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F83m9ur41hdnciopl66y9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F83m9ur41hdnciopl66y9.png" alt="Anime terminator (learning async/await) haunting girl hiding under a desk (you)." width="680" height="719"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You might know the difference between synchronous and asynchronous code, but you're completely lost in the application of it.&lt;/p&gt;

&lt;p&gt;At this rate, it's hard to imagine how you'll ever &lt;strong&gt;wrap your head around asynchronous JavaScript&lt;/strong&gt;. 😫&lt;/p&gt;

&lt;p&gt;But learning async/await doesn't have to be scary!&lt;/p&gt;

&lt;p&gt;With a little guidance and the right approach, you can write &lt;strong&gt;modern asynchronous code that just works&lt;/strong&gt;. Not next month, or next week, but &lt;em&gt;today&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;It's true, async/await is unintuitive at first.. but only because you haven't built a mental model for it, &lt;em&gt;yet&lt;/em&gt;!&lt;/p&gt;

&lt;p&gt;To understand async/await we have to talk a little bit about promises first. Since async/await is built on top of promises, when you're writing async/await you're in fact dealing with promises under the hood.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's a &lt;code&gt;Promise&lt;/code&gt;?
&lt;/h2&gt;

&lt;p&gt;Put simply, a &lt;code&gt;Promise&lt;/code&gt; is a JavaScript object that represents a future value. It holds two pieces of information: the promise &lt;em&gt;state&lt;/em&gt;, and a &lt;em&gt;value&lt;/em&gt; or &lt;em&gt;error&lt;/em&gt; (depending on the state).&lt;/p&gt;

&lt;p&gt;A promise can be in one of these states:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;pending&lt;/em&gt; —  initial state, the operation is in progress&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;fulfilled&lt;/em&gt; — the operation completed successfully&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;rejected&lt;/em&gt; — the operation failed&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A promise is &lt;em&gt;settled&lt;/em&gt; when the promise has either fulfilled or rejected, but not pending. A promise eventually &lt;em&gt;fulfills&lt;/em&gt; with a value or &lt;em&gt;rejects&lt;/em&gt; with an error (or reason).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8m9d29ckyoe804646u7t.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8m9d29ckyoe804646u7t.png" alt="new Promise(executor) with state: " width="800" height="405"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A function that returns a promise is by definition an &lt;em&gt;asynchronous&lt;/em&gt; function. (remember this, we'll come back to it later)&lt;/p&gt;

&lt;p&gt;Even though the promise is returned synchronously, the value &lt;em&gt;inside&lt;/em&gt; the promise is asynchronous and can only be accessed &lt;em&gt;after&lt;/em&gt; the promise has fulfilled.&lt;/p&gt;

&lt;h2&gt;
  
  
  What does &lt;code&gt;await&lt;/code&gt; actually do?
&lt;/h2&gt;

&lt;p&gt;When you add the await keyword in front of a promise you instruct the JavaScript runtime to pause execution inside the current function, wait until the promise settles, and only after the promise has settled, continue executing the rest of the code inside that function.&lt;/p&gt;



&lt;p&gt;Await &lt;em&gt;guarantees&lt;/em&gt; that you have access to an asynchronous value past a certain point. The runtime won't execute any further code inside the function until the promise fulfills with the value (or rejects with an error).&lt;/p&gt;

&lt;p&gt;One thing to keep in mind is that &lt;strong&gt;starting an asynchronous operation and awaiting its result are two &lt;em&gt;separate&lt;/em&gt; actions&lt;/strong&gt;. This becomes clear when you write them on different lines.&lt;/p&gt;



&lt;p&gt;Therefore, await is solely responsible for pausing further execution until the asynchronous operation has completed. It is &lt;em&gt;not&lt;/em&gt; what starts the asynchronous operation.&lt;/p&gt;

&lt;h2&gt;
  
  
  How about &lt;code&gt;async&lt;/code&gt;?
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;async&lt;/code&gt; keyword grants a special ability to a function.&lt;/p&gt;

&lt;p&gt;A function marked as async can pause execution anywhere inside its body. In other words, the function is allowed to use the await keyword. Await can &lt;em&gt;only&lt;/em&gt; be used inside async functions. (you'll understand why in a bit)&lt;/p&gt;

&lt;p&gt;An async function has two important properties:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;It &lt;em&gt;always&lt;/em&gt; returns a Promise&lt;/li&gt;
&lt;li&gt;You can use the await keyword inside its scope&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;When you return a &lt;em&gt;non&lt;/em&gt;-Promise value inside an async function, the value is wrapped inside a Promise before being returned.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getFive&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;getFive&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// Promise { ... }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Remember what I said earlier about functions that return a promise — they're by definition asynchronous. Therefore, a function marked as async is &lt;em&gt;always&lt;/em&gt; asynchronous.&lt;/p&gt;

&lt;p&gt;A non-&lt;code&gt;async&lt;/code&gt; function that returns a promise is also asynchronous. The following code is practically the same as the one above:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getFive&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;getFive&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// Promise { ... }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All other functions are considered synchronous functions.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fht7s2yggtg44lq664gbw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fht7s2yggtg44lq664gbw.png" alt="Decision tree to determine whether a function is synchronous or asynchronous." width="800" height="554"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why &lt;code&gt;async&lt;/code&gt; &amp;amp; &lt;code&gt;await&lt;/code&gt; are inseparable
&lt;/h2&gt;

&lt;p&gt;Knowing that await pauses execution inside a function and that a non-async function is synchronous if it doesn't return a promise, you can start to see why the following code doesn't work:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getFive&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// function is not async&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;five&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetchFive&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// 🚫 doesn't work, can't use await&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;five&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;How can &lt;code&gt;getFive()&lt;/code&gt; synchronously return &lt;code&gt;five&lt;/code&gt; if it needs to wait for &lt;code&gt;fetchFive()&lt;/code&gt; first?&lt;/p&gt;

&lt;p&gt;Put differently, how can you wait for an asynchronous value and then proceed to return it synchronously?&lt;/p&gt;

&lt;p&gt;You simply &lt;em&gt;can't&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;That's why await can only be used inside a function declared with the async keyword. An async function wraps the return value in a promise which makes the value asynchronous.&lt;/p&gt;

&lt;p&gt;Hopefully you have a better understanding of async/await by now. Go ahead and use it in your projects!&lt;/p&gt;

&lt;h2&gt;
  
  
  Transform Callbacks into Clean Async Code! 🚀
&lt;/h2&gt;

&lt;p&gt;Tired of messy callback code? Download this &lt;strong&gt;FREE 5-step guide&lt;/strong&gt; to master async/await and simplify your asynchronous code.&lt;/p&gt;

&lt;p&gt;In just a few steps, you'll transform complex logic into readable, &lt;em&gt;modern JavaScript&lt;/em&gt; that's easy to maintain. With clear visuals, each step breaks down the process so you can follow along effortlessly.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkuh49fp3fcc0hs1axenb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkuh49fp3fcc0hs1axenb.png" alt="Refactoring Callbacks Guide Preview" width="800" height="494"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://pages.maximorlov.com/refactoring-callbacks-guide" class="ltag_cta ltag_cta--branded" rel="noopener noreferrer"&gt;Get the FREE guide&lt;/a&gt;
&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>beginners</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
