<?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: Vincas Stonys</title>
    <description>The latest articles on DEV Community by Vincas Stonys (@vincasstonys).</description>
    <link>https://dev.to/vincasstonys</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%2F929457%2F9380e641-c2da-483b-ac35-66a53c7495a3.png</url>
      <title>DEV Community: Vincas Stonys</title>
      <link>https://dev.to/vincasstonys</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/vincasstonys"/>
    <language>en</language>
    <item>
      <title>10 Tips to Succeed as a Junior Developer</title>
      <dc:creator>Vincas Stonys</dc:creator>
      <pubDate>Tue, 07 Feb 2023 10:12:39 +0000</pubDate>
      <link>https://dev.to/vincasstonys/succeed-as-a-junior-developer-1f7n</link>
      <guid>https://dev.to/vincasstonys/succeed-as-a-junior-developer-1f7n</guid>
      <description>&lt;p&gt;Being a junior developer is hard. At the start of my career, I used to feel overwhelmed, like I didn't know what I was doing. And that it was only a matter of time until I got exposed as the imposter that I was.&lt;/p&gt;

&lt;p&gt;While I was at school and university, I seemed to have it all figured out - as long as you go to classes and maybe study a little, you're good. But when you're on your first day at work - what the hell do you do?&lt;/p&gt;

&lt;p&gt;There were all these people I'd never met before (everyone was so serious), following some processes I didn't know (scrum-what?) And the codebase - larger and scarier than I've ever seen. Not to mention written in programming languages and frameworks I've never heard of (does anyone code in Groovy or use Ext.js anyway?)&lt;/p&gt;

&lt;p&gt;I wish there was someone to reassure me or some sort of guidelines I could follow to not only survive but &lt;em&gt;succeed&lt;/em&gt;. Well then...&lt;/p&gt;

&lt;p&gt;After having been a professional software developer for over 7 years now, here's what I wish I knew at the beginning of my career as a junior developer.&lt;/p&gt;

&lt;h2&gt;
  
  
  1) First, Relax
&lt;/h2&gt;

&lt;p&gt;When you're at your first job as a junior developer it's easy to get the impression you're expected to deliver results (and quickly). At least that's how it was for me - people around me were stressed, constantly talking about some deadline they have.&lt;/p&gt;

&lt;p&gt;Don't get caught up in it. You as a junior developer are there to &lt;em&gt;learn&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1571400877029605376-637" src="https://platform.twitter.com/embed/Tweet.html?id=1571400877029605376"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1571400877029605376-637');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1571400877029605376&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;Nobody expects you to deliver. For the company - you're an investment. And to be a good investment - you need to &lt;em&gt;grow&lt;/em&gt; (no... I meant your skills 🤦‍♂️).&lt;/p&gt;

&lt;p&gt;Take your time with whatever you're doing, learn as much as you can, ask questions and try to enjoy the process.&lt;/p&gt;

&lt;h2&gt;
  
  
  2) Solve Problems Yourself
&lt;/h2&gt;

&lt;p&gt;I remember when I discovered GitHub I wanted to use a 3rd party library for any problem I had. After all, why write the code yourself, if someone else already has?&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Wrong&lt;/em&gt;. Your early career is a time for investments. You should try to solve every problem yourself even if it isn't optimal.&lt;/p&gt;

&lt;p&gt;Over time you'll build up a database of go-to solutions in your head. And for the more complex problems, you'll know what to look for in a 3rd party solution - because you're familiar with the problem and know what a good solution should look like.&lt;/p&gt;

&lt;p&gt;Again, your job as a junior developer is to learn first, and you learn nothing if you never try solving problems yourself.&lt;/p&gt;

&lt;h2&gt;
  
  
  3) Ask For Help Early
&lt;/h2&gt;

&lt;p&gt;As a junior developer, you're bound to get stuck eventually (a lot, actually). This is where many junior developers get into trouble. They think they mustn't bother anyone with their stupid issues and instead pretend they're fine.&lt;/p&gt;

&lt;p&gt;That's a huge red flag  🚩.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Always ask for help early&lt;/em&gt;. As a rule of thumb, if you're stuck, feel free to spend 15-30 minutes trying to figure it out yourself, but then &lt;em&gt;please&lt;/em&gt; ask for help.&lt;/p&gt;

&lt;p&gt;There's nothing worse than junior developers who're struggling but are pretending they're fine.&lt;/p&gt;

&lt;h2&gt;
  
  
  4) Ask For Help Correctly
&lt;/h2&gt;

&lt;p&gt;As a junior developer, I was scared to ask for help because I thought the senior devs will be annoyed with my questions. And frankly, they probably were. But there is a way to make the experience pleasant for both you and the senior devs.&lt;/p&gt;

&lt;p&gt;Here is what worked well for me 👇&lt;/p&gt;

&lt;h3&gt;
  
  
  Batch your questions.
&lt;/h3&gt;

&lt;p&gt;Don't bother the senior dev every time you run into a problem. Write your question down and work on something else for a while. Once you have 3 or more questions (or some reasonable time has passed), go and ask them for help.&lt;/p&gt;

&lt;h3&gt;
  
  
  Do your part
&lt;/h3&gt;

&lt;p&gt;Try to solve the problem first, then look for a solution online (e.g. documentation) and when you eventually ask for help - explain what you've tried. It's very frustrating when junior devs run into a problem, try nothing to solve it, then expect you to solve the problem for them.&lt;/p&gt;

&lt;h3&gt;
  
  
  Show willingness to learn
&lt;/h3&gt;

&lt;p&gt;Never ask for the answer. Show them that you want to solve the problem yourself, and ask for a roadmap instead. You may ask for steps to find the solution, but if you're just asking for their solution, you're learning nothing (see tip #2).&lt;/p&gt;

&lt;h2&gt;
  
  
  5) Practice Humility
&lt;/h2&gt;

&lt;p&gt;Senior developers know better (even if they don't). Don't be a rebel. Understand that you most likely know less than someone who's been doing this thing for years, and follow their instructions exactly.&lt;/p&gt;

&lt;p&gt;Yes, there are stupid senior engineers. And yes, there are people who're just mean. Accept their criticism, learn what you can from them, and ignore the rest. Don't get discouraged by criticism.&lt;/p&gt;

&lt;p&gt;These realizations have helped me tremendously in dealing with imposter syndrome and negative feedback:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Your code is not you.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Nobody &lt;em&gt;really&lt;/em&gt; knows what they're doing.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Your time to shine will come - there will be opportunities for you to take on responsibility and show your creativity. When that time comes - overdeliver.&lt;/p&gt;

&lt;h2&gt;
  
  
  6) Take Ownership and Responsibility
&lt;/h2&gt;

&lt;p&gt;This is the best way to shake off the "junior" label. From the start, I was happy to help other junior developers, which in the eyes of others has made me the most "senior" of the lot (even though we started at the same time with no prior experience).&lt;/p&gt;

&lt;p&gt;Over time, I've learned some cool new tech by myself, which got popular (TypeScript), so then even senior devs went to me for help (huge confidence boost). In 2 of the companies I've worked at I was known as "The TypeScript Guy". Creating a niche for yourself is an excellent way to level up your career.&lt;/p&gt;

&lt;p&gt;Voice your opinions, share your learnings, and when the opportunity for you to step up and show initiative comes - take it.&lt;/p&gt;

&lt;p&gt;Here's a tip from me - &lt;em&gt;write end-to-end tests&lt;/em&gt;. Nobody likes setting them up, nobody likes writing them, and nobody likes to be responsible for them. That's the perfect opportunity for a junior dev to show initiative 😉.&lt;/p&gt;

&lt;h2&gt;
  
  
  7) Build Side Projects
&lt;/h2&gt;

&lt;p&gt;Most good developers I know build stuff in their own time. And I know many bad ones that don't. Building side projects is the best way to fast-track your career.&lt;/p&gt;

&lt;p&gt;Let me put it this way - when you go to an interview, the interviewer is looking for proof that you're good, that you can get shit done. When you can point him to a real-world app you've built and deployed by yourself - you have undeniable proof that you can build and release apps.&lt;/p&gt;

&lt;p&gt;I improved the most as a developer when I was building my side project &lt;a href="http://mediabits.io" rel="noopener noreferrer"&gt;mediabits.io&lt;/a&gt;. Also, it's been invaluable for my career - it has quite literally doubled my salary.&lt;/p&gt;

&lt;p&gt;Instead of being a mere coding monkey, you become someone who builds products.&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%2F1tz060yvbs4y859mlr5q.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%2F1tz060yvbs4y859mlr5q.png" alt="What you need to know Venn diagram" width="800" height="478"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ideally, the stuff you build should be something you need yourself and something you've built on your own (don't just follow a tutorial). Here are some ideas 👇&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1558158514618507268-58" src="https://platform.twitter.com/embed/Tweet.html?id=1558158514618507268"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1558158514618507268-58');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1558158514618507268&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;h2&gt;
  
  
  8) Focus on Fundamentals
&lt;/h2&gt;

&lt;p&gt;Once you start building side-projects it's easy to get caught up trying to learn all the new technologies. This is overwhelming.&lt;/p&gt;

&lt;p&gt;Make it your goal to deliver a working app, instead of learning the latest-greatest shiny new framework. Just pick a solid technology that's been around for a while and use that. New technologies come and go, but fundamentals stay.&lt;/p&gt;

&lt;p&gt;Guess what, most new tech is just a flavor of the same old thing with some sprinkles on top. It's a lot better to spend time mastering JavaScript instead of learning about the nitty-gritty details of react-router.&lt;/p&gt;

&lt;p&gt;Don't make it harder than it needs to be. You're inevitably going to learn &lt;em&gt;a lot&lt;/em&gt; anyway.&lt;/p&gt;

&lt;h2&gt;
  
  
  9) Learn in Public
&lt;/h2&gt;

&lt;p&gt;Not writing a blog or creating YouTube videos is the biggest regret I have from my early career. Even as I'm writing this blog, I've already forgotten a lot of the struggles I've had as a beginner.&lt;/p&gt;

&lt;p&gt;Two things are well-known:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;We learn best when we teach what we learn.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We learn best not from experts, but from someone who's only one step ahead.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Somebody else will find your content invaluable, and as a bonus, you'll be building an audience that you can monetize later to earn some side income.&lt;/p&gt;

&lt;p&gt;At the moment, &lt;a href="http://hashnode.dev" rel="noopener noreferrer"&gt;hashnode.dev&lt;/a&gt; and &lt;a href="http://dev.to"&gt;dev.to&lt;/a&gt; are the easiest way to start blogging for developers.&lt;/p&gt;

&lt;h2&gt;
  
  
  10) Don’t Stay In Your First Job for Too Long
&lt;/h2&gt;

&lt;p&gt;This one is a bit controversial and you're free to ignore it, but it's something I regret doing early in my career.&lt;/p&gt;

&lt;p&gt;I think it's best to change your first job after 1-2 years in the company (unless you landed a job at Google in which case, ignore what I tell you). Here's why:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Your opportunities for learning will be mostly exhausted.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You'll forever be junior in the eyes of the devs you first worked with.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You were underpaid when you started, and you will stay that way until you get a new job.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Money should not be the reason to leave your first job, but just keep in mind that salary grows relative to your current salary (usually around 5-10%). A market-level salary for a developer with 2-3 years of exp is at least 2x higher than an entry-level salary (quick math 🤔 ~50% increase for every year).&lt;/p&gt;

&lt;p&gt;If you feel like you're becoming stagnant, don't let the fear or "loyalty" stop you from getting another job. Your company is not your family, as much as they wish it were true.&lt;/p&gt;

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

&lt;p&gt;Early career as a junior developer is a scary period, but it gets very rewarding later on. I'm glad I had a few friends doing the same thing and struggling with the same feelings. I can't imagine how lonely it would've felt otherwise.&lt;/p&gt;

&lt;p&gt;If you don't, I want you to at least have the guidelines I wish I had when I was just starting out. It all comes down to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Learn as much as you can;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Share what you learn;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Build a solid foundation both in terms of skills and career.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Introduce yourself in the comments and let me know what you're struggling with. Feel free to connect with me on &lt;a href="https://twitter.com/VincasStonys" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;, where I share regular tips for junior developers building their first web app with React.&lt;/p&gt;




&lt;p&gt;This is a repost from my blog at &lt;a href="https://codefrontend.com/succeed-as-a-junior-developer/" rel="noopener noreferrer"&gt;codefrontend.com&lt;/a&gt;, come say hi.&lt;/p&gt;

</description>
      <category>linux</category>
      <category>opensource</category>
      <category>discuss</category>
    </item>
    <item>
      <title>Learn to Use React Portals in the Real World</title>
      <dc:creator>Vincas Stonys</dc:creator>
      <pubDate>Fri, 29 Jul 2022 06:55:05 +0000</pubDate>
      <link>https://dev.to/vincasstonys/learn-to-use-react-portals-in-the-real-world-31b1</link>
      <guid>https://dev.to/vincasstonys/learn-to-use-react-portals-in-the-real-world-31b1</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Portals provide a first-class way to render children into a DOM node that exists outside the DOM hierarchy of the parent component. - React Docs&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In simple terms - portals allow you to render the component’s content into an element that’s outside of where the component’s content is rendered normally.&lt;/p&gt;

&lt;p&gt;In the real world, they allow us to implement tooltips, dropdowns, modals, and overlays that are not affected by positioning and overflow rules of other elements.&lt;/p&gt;

&lt;p&gt;In this post I’ll show:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;how portals work through an example;&lt;/li&gt;
&lt;li&gt;an example of a tooltip with a problem that portals may help solve;&lt;/li&gt;
&lt;li&gt;an example of such a tooltip implemented using portals.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;ℹ If you’re a beginner, who’s just starting out, don’t worry about portals. You most likely won’t need to use them for a long time. Just keep building your app and if you’re faced with problems implementing modals, toasts, dropdowns, overlays, or tooltips - come back to read this post.&lt;/p&gt;

&lt;h2&gt;
  
  
  How do React portals work?
&lt;/h2&gt;

&lt;p&gt;Let’s say we have a yellow disc and two boxes - blue and green:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function YellowDisc() {
  return (
    &amp;lt;div
      style={{
        width: 50,
        height: 50,
        background: "yellow",
        borderRadius: "50%"
      }}
    /&amp;gt;
  );
}

function BlueBox() {
  return (
    &amp;lt;div
      style={{
        width: 100,
        height: 100,
        background: "blue"
      }}
    /&amp;gt;
  );
}

function GreenBox() {
  return (
    &amp;lt;div
      style={{
        width: 100,
        height: 100,
        background: "green"
      }}
    /&amp;gt;
  );
}

function App() {
  return (
    &amp;lt;div&amp;gt;
      &amp;lt;YellowDisc /&amp;gt;
      &amp;lt;BlueBox /&amp;gt;
      &amp;lt;GreenBox /&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here's the resulting yellow disc, blue box, and green box.&lt;br&gt;
‌&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_bXuUyNb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9wqegx3u1azzjqoy6y98.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_bXuUyNb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9wqegx3u1azzjqoy6y98.png" alt="Example three boxes" width="237" height="536"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If we wanted to add the yellow disc into the blue box, the simplest way to do that is to have the blue ball render the disc:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function BlueBox() {
  return (
    &amp;lt;div
      style={{
        width: 100,
        height: 100,
        background: "blue"
      }}
    &amp;gt;
      &amp;lt;YellowDisc /&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}

function App() {
  return (
    &amp;lt;div&amp;gt;
      &amp;lt;BlueBox /&amp;gt;
      &amp;lt;GreenBox /&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The yellow disc is in the blue box:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--M9Uz1Hsz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bp9601d504ig59oq97du.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--M9Uz1Hsz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bp9601d504ig59oq97du.png" alt="Yellow disc in blue box" width="232" height="429"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The blue box now owns the yellow disc.&lt;/p&gt;

&lt;p&gt;Let’s say that the green box wants to borrow the yellow disc, but the blue box won’t simply let the green box render it. The blue box wants to “own” the disc and stay informed about what happens with it, but it will allow the green box borrow it.&lt;/p&gt;

&lt;p&gt;Portals allow the blue box to render the yellow disc into the green box, without the green box owning the yellow disc:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { useEffect, useState } from "react";
import ReactDOM from "react-dom";

function BlueBox() {
  const [element, setElement] = useState&amp;lt;HTMLElement&amp;gt;();

  useEffect(() =&amp;gt; {
    const el = document.getElementById("green-box");
    if (el) {
      setElement(el);
    }
  }, []);

  if (!element) {
    return null;
  }

  return (
    &amp;lt;div
      style={{
        width: 100,
        height: 100,
        background: "blue"
      }}
    &amp;gt;
      {ReactDOM.createPortal(&amp;lt;YellowDisc /&amp;gt;, element)}
    &amp;lt;/div&amp;gt;
  );
}

function GreenBox() {
  return (
    &amp;lt;div
      id="green-box"
      style={{
        width: 100,
        height: 100,
        background: "green"
      }}
    /&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The yellow disc is now in the green box:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--BbCHsRYp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xdkhnhc1yckyl3ah0i9t.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--BbCHsRYp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xdkhnhc1yckyl3ah0i9t.png" alt="Yellow disc in green box" width="234" height="431"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here’s what happened:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;I gave the green box an &lt;code&gt;id&lt;/code&gt; attribute so that I could query the DOM element for the portal to render into.&lt;/li&gt;
&lt;li&gt;The blue box uses the portal to render the yellow disk inside the green box.&lt;/li&gt;
&lt;li&gt;I used the state to keep track of the reference to the green box and useEffect to find the element after both boxes have been rendered. If I tried to find the green box by id outside of &lt;code&gt;useEffect&lt;/code&gt;, then I might not find it. Depending on the nesting and element order, the green box might not be rendered yet. However, in the real world, we usually render into &lt;code&gt;document.body&lt;/code&gt; which always exists and we can query it directly without the &lt;code&gt;useEffect&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  React event propagation using portals
&lt;/h3&gt;

&lt;p&gt;Well, rendering the element is not something special. In fact, you may achieve the same result without using portals, by using refs.&lt;/p&gt;

&lt;p&gt;However, portals give us one advantage - they allow the React events to bubble up the React component tree to their parent React elements.&lt;/p&gt;

&lt;p&gt;This is what allows the blue box to keep tabs on the events from the yellow disc, even though it’s rendered inside of the green box.&lt;/p&gt;

&lt;p&gt;In fact, to observe this behavior, add &lt;code&gt;onClick={() =&amp;gt; console.log("blue clicked!")}&lt;/code&gt; to the blue box &lt;code&gt;div&lt;/code&gt; and &lt;code&gt;onClick={() =&amp;gt; console.log("green clicked!")}&lt;/code&gt; to the green box &lt;code&gt;div&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;You will notice that the click event on the yellow disc bubbles up and triggers a click event handler on the blue box. But it doesn’t trigger it on the green box. That’s what I mean when I say that the blue box owns the yellow disc.&lt;/p&gt;

&lt;p&gt;See it in action here:&lt;/p&gt;

&lt;p&gt;&lt;iframe src="https://codesandbox.io/embed/react-portals-9cnm2d"&gt;
&lt;/iframe&gt;
&lt;br&gt;
‌&lt;br&gt;
If you inspect the DOM now, you will see that the green box now contains the disc even if the blue box owns it:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--RBpjtR0b--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/scqb3xms29j1nqsblelk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--RBpjtR0b--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/scqb3xms29j1nqsblelk.png" alt="DOM tree" width="606" height="150"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;How come the blue box receives the events and not the green box?&lt;/p&gt;

&lt;p&gt;There is no magic here. This is simply because React uses its own event system which works in parallel with the DOM event system. React events bubble up the React component tree, and DOM events bubble up the DOM tree.&lt;/p&gt;
&lt;h1&gt;
  
  
  $ What problems do portals solve?
&lt;/h1&gt;

&lt;p&gt;At this point, you may understand how portals work, but how do you know when to use them?&lt;/p&gt;

&lt;p&gt;You won’t need to use portals often. If you’re a beginner, you most likely won’t need to use them at all for a long time. Even in the above example, if we just let the green box render the circle, we’d have no problems. However, there are some cases where portals can be life-savers.&lt;/p&gt;
&lt;h3&gt;
  
  
  Tooltips in the real world
&lt;/h3&gt;

&lt;p&gt;Let’s say you’re building a tooltip:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React, { useState } from "react";

interface Props {
  text: string;
  children: React.ReactNode;
}

function Tooltip({ text, children }: Props) {
  const [isVisible, setVisible] = useState(false);

  const handleMouseOver = () =&amp;gt; setVisible(true);
  const handleMouseOut = () =&amp;gt; setVisible(false);

  return (
    &amp;lt;div
      style={{ position: "relative" }}
      onMouseOver={handleMouseOver}
      onMouseOut={handleMouseOut}
    &amp;gt;
      {children}
      {isVisible &amp;amp;&amp;amp; (
        &amp;lt;div
          style={{
            top: "100%",
            left: 0,
            position: "absolute",
            paddingTop: 5,
            zIndex: 10
          }}
        &amp;gt;
          &amp;lt;div
            style={{
              background: "black",
              color: "white"
            }}
          &amp;gt;
            {text}
          &amp;lt;/div&amp;gt;
        &amp;lt;/div&amp;gt;
      )}
    &amp;lt;/div&amp;gt;
  );
}

function App() {
  return (
    &amp;lt;div&amp;gt;
      &amp;lt;Tooltip text="Clicky clicky"&amp;gt;
        &amp;lt;button&amp;gt;Button&amp;lt;/button&amp;gt;
      &amp;lt;/Tooltip&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}

export default App;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;‌&lt;br&gt;
If you hover the button, you get a tooltip below that says Clicky clicky. It’s basic but works fine. That’s how I would start out building a simple tooltip.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--cJTHEIr---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/oetqf0flt97mkl7txd5r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--cJTHEIr---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/oetqf0flt97mkl7txd5r.png" alt="Simple tooltip" width="251" height="154"&gt;&lt;/a&gt;&lt;br&gt;
‌&lt;br&gt;
However, what if at some point we need to use it in a container, that hides the overflowing content? To see the problem, add &lt;code&gt;style={{ height: 35, overflow: "hidden" }}&lt;/code&gt; to the &lt;code&gt;div&lt;/code&gt; in &lt;code&gt;App&lt;/code&gt; component. Our tooltip gets cut off.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--qn3AWVsQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ifya4wsz5pynt2xw4b9l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qn3AWVsQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ifya4wsz5pynt2xw4b9l.png" alt="Tooltip issue" width="253" height="146"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That’s a real-world issue that portals can help us solve. Also, you may have noticed that the tooltip component wraps its children with a relatively positioned div. This can make it difficult to use such tooltips in practice because you’d need to put extra effort to ensure they don’t mess up the layout.&lt;/p&gt;

&lt;p&gt;See it in action:&lt;/p&gt;

&lt;p&gt;&lt;iframe src="https://codesandbox.io/embed/react-portals-tooltip-example-9lp4wu"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h3&gt;
  
  
  How do portals help to implement tooltips?
&lt;/h3&gt;

&lt;p&gt;The general way to solve the clipping issue is:&lt;/p&gt;

&lt;p&gt;On hover, determine the anchor point for the tooltip on-screen, normally using &lt;code&gt;getBoundingClientRect&lt;/code&gt; or &lt;code&gt;offsetLeft&lt;/code&gt; and &lt;code&gt;offsetTop&lt;/code&gt; properties on the element.&lt;br&gt;
Render the tooltip as close to &lt;code&gt;&amp;lt;body&amp;gt;&lt;/code&gt; element as possible.&lt;br&gt;
Use &lt;code&gt;fixed&lt;/code&gt; position on the tooltip and position it near the anchor element using the anchor point coordinates we got previously.&lt;br&gt;
Whoa, this quickly got a lot more complex. And because the tooltip is now a free-floating element on the screen, we may need to handle edge cases, such as:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The tooltip position may need to update when we scroll;&lt;/li&gt;
&lt;li&gt;The tooltip should re-position itself near the screen edges if it goes out of the screen.&lt;/li&gt;
&lt;li&gt;The tooltip should work well with other free-floating elements such as modals.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;None of these issues are trivial to solve, that’s why we have libraries whose sole purpose is to manage the positioning of floating elements, like &lt;a href="https://www.react-laag.com/"&gt;react-laag&lt;/a&gt; and &lt;a href="https://popper.js.org/"&gt;popperjs&lt;/a&gt;. In fact, you’re probably better off not building a custom tooltip solution of your own. Been there, done that…&lt;/p&gt;

&lt;p&gt;Here’s what such a tooltip implementation may look like in the real world:&lt;br&gt;
‌&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React, { useState } from "react";
import ReactDOM from "react-dom";

interface Props {
  text: string;
  children: React.ReactNode;
}

function Tooltip({ text, children }: Props) {
  // Position of the bottom edge of the anchor element.
  // Doubles as isVisible state: null means hidden
  const [position, setPosition] = useState&amp;lt;{
    x: number;
    y: number;
  } | null&amp;gt;(null);

  const handleMouseOver = (
    e: React.MouseEvent&amp;lt;HTMLElement&amp;gt;
  ) =&amp;gt; {
    // Place the tooltip near the anchor's bottom edge on the screen
    const bounds = e.currentTarget.getBoundingClientRect();
    setPosition({
      x: bounds.x,
      y: bounds.y + bounds.height
    });
  };

  const handleMouseOut = () =&amp;gt; setPosition(null);

  const anchorProps = {
    onMouseOver: handleMouseOver,
    onMouseOut: handleMouseOut
  };

  // Clones the child element to remove the div wrapper around it.
  // Child node must accept or forward mouse events.
  // We can't set even handlers on text, so we wrap it with &amp;lt;span&amp;gt;.
  const anchor = React.isValidElement(children) ? (
    React.cloneElement(children, anchorProps)
  ) : (
    &amp;lt;span {...anchorProps}&amp;gt;{children}&amp;lt;/span&amp;gt;
  );

  // We use react portal to render the tooltip into document.body.
  // To place it near the button, we use the position from the event.
  // The position is "fixed" so it won't be affected by overflow rules.
  return (
    &amp;lt;&amp;gt;
      {anchor}
      {position &amp;amp;&amp;amp;
        ReactDOM.createPortal(
          &amp;lt;div
            style={{
              top: position.y,
              left: position.x,
              position: "fixed",
              paddingTop: 5,
              zIndex: 10
            }}
          &amp;gt;
            &amp;lt;div
              style={{
                background: "black",
                color: "white"
              }}
            &amp;gt;
              {text}
            &amp;lt;/div&amp;gt;
          &amp;lt;/div&amp;gt;,
          document.body
        )}
    &amp;lt;/&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;‌&lt;br&gt;
Here’s what I did:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;I’ve replaced &lt;code&gt;isVisible&lt;/code&gt; with the tooltip’s position on the screen. If the position is set, it means the tooltip is visible, otherwise, it’s hidden.&lt;/li&gt;
&lt;li&gt;I changed the hover event handler to get the button’s height and position on the screen. Then I use them to place the tooltip at the bottom edge of the button.&lt;/li&gt;
&lt;li&gt;I assigned the event handlers to the anchor, by cloning it first. This allows me to remove the &lt;code&gt;div&lt;/code&gt; wrapper from the tooltip, so it doesn’t affect the layout in any way. You could leave the wrapper and pass it the event handlers, but I don’t like it when commonly used components, such as tooltips, make me think about how they will affect layouts.&lt;/li&gt;
&lt;li&gt;Finally, I used a React portal to render the tooltip into &lt;code&gt;document.body&lt;/code&gt;, so that it’s not affected by the parent elements’ layout rules. Then I changed its position to &lt;code&gt;fixed&lt;/code&gt;, and set its coordinates on the screen to be at the bottom of the button.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you test it now, you will see that the tooltip works exactly the same, but it’s not affected by the &lt;code&gt;overflow: hidden&lt;/code&gt; that we set on the button’s container &lt;code&gt;div&lt;/code&gt;. If you implemented dropdowns, modals, and toasts in a similar fashion, they would also be unaffected by the layout rules.&lt;/p&gt;

&lt;p&gt;However, it is important to realize the tradeoffs of this implementation:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The code is now harder to understand.&lt;/li&gt;
&lt;li&gt;We need to do more work because we need to sync the tooltip's position with its anchor element. It can be hard:

&lt;ul&gt;
&lt;li&gt;If the anchor or the tooltip is animated or change sizes frequently.&lt;/li&gt;
&lt;li&gt;When we scroll the page we should reposition or hide the tooltip.&lt;/li&gt;
&lt;li&gt;If the tooltip is near the edge of the screen, we may want to adjust its placement to stay inside the screen.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Here’s the final implementation in action:&lt;/p&gt;

&lt;p&gt;&lt;iframe src="https://codesandbox.io/embed/react-portals-tooltip-portal-example-5d90bg"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

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

&lt;p&gt;The problems and solutions, where we may apply React portals, follow a similar pattern:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;An element is affected by the parent element’s positioning or overflow rules.&lt;/li&gt;
&lt;li&gt;Using portals, we render the component in another place, where it’s no more affected by those rules.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Here are some common real-world use cases for portals: tooltips, dropdowns, modals, overlays, and toasts.&lt;/p&gt;

&lt;p&gt;Portals often make the implementation more complex and introduce edge cases, so I would only use them if no simpler method is available. Honestly, I don’t see much wrong with the original implementation of the tooltip in my example, and I would start with that.&lt;/p&gt;

&lt;p&gt;In the real world, when faced with the above use cases, it’s probably simpler to use a reliable UI component for modal, dropdown, or tooltip instead of building your own.&lt;/p&gt;

&lt;p&gt;Nevertheless, it’s a worthwhile exercise to try to build your own implementation to get familiar with the problems. Solving them will make you a better developer, no matter what skill level you’re at.&lt;/p&gt;

&lt;p&gt;Though it’s probably best if you do that in your own sandbox project...&lt;/p&gt;




&lt;p&gt;This article is republished from my &lt;a href="https://codefrontend.com"&gt;programming blog&lt;/a&gt;. Follow me on &lt;a href="https://twitter.com/VincasStonys"&gt;Twitter&lt;/a&gt; to learn how to build real-world web applications using React.&lt;/p&gt;

&lt;p&gt;If you want to master Promises, the best way to do that is by implementing them from scratch. I explain how in this article: &lt;a href="https://dev.to/vincasstonys/asynchronous-javascript-learn-promises-from-scratch-2i91"&gt;Asynchronous Javascript - Learn Promises From Scratch&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>react</category>
      <category>webdev</category>
      <category>beginners</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Asynchronous Javascript - Learn Promises From Scratch</title>
      <dc:creator>Vincas Stonys</dc:creator>
      <pubDate>Tue, 19 Jul 2022 07:21:52 +0000</pubDate>
      <link>https://dev.to/vincasstonys/asynchronous-javascript-learn-promises-from-scratch-2i91</link>
      <guid>https://dev.to/vincasstonys/asynchronous-javascript-learn-promises-from-scratch-2i91</guid>
      <description>&lt;p&gt;JavaScript is a synchronous language at its core, meaning that only a single line of code runs at any time. That means that time spent executing some part of the code delays the execution of other code. This includes painting things on the screen, handling user input, or doing math.&lt;/p&gt;

&lt;p&gt;When building frontend applications we often need to deal with asynchronous operations, such as user input or HTTP requests. In the browser they may run on a separate thread, so how do we deal with this asynchronicity in a synchronous language like JavaScript?&lt;/p&gt;

&lt;p&gt;Understanding this part of JavaScript is essential to building real-world applications. And that's what we're going to take a look at in this article.&lt;/p&gt;

&lt;p&gt;We'll learn about:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Callbacks&lt;/strong&gt; - how callbacks can be used to deal with asynchronous code, and how they lead to callback hell.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Promises&lt;/strong&gt; - how to use promises to make callbacks manageable. We'll also write our own implementation of the basic promise API to understand how they work.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Async/await&lt;/strong&gt; - how to use the new await/async API to make promises even easier to work with.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;📚 Synchronicity reduces the cognitive load when writing JavaScript code since you don't need to concern yourself with multiple threads accessing and updating the same data. However, sometimes it's necessary to break out of the single thread for computationally expensive operations. To understand how to execute your own code asynchronously learn about &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers"&gt;Web Workers&lt;/a&gt; in the browser and &lt;a href="https://deepsource.io/blog/nodejs-worker-threads/"&gt;Worker Threads&lt;/a&gt; in Node.js.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Callback functions
&lt;/h2&gt;

&lt;p&gt;It would be impractical if making an HTTP request blocked the code until we got a response. Even if it came back in 100 milliseconds, that's still &lt;em&gt;ages&lt;/em&gt; in computer time. Luckily, JavaScript allows us to provide &lt;strong&gt;callback functions&lt;/strong&gt; to asynchronous APIs.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;📌 A callback is a function that's passed as an argument to another function to be called by that function at a later time. Often, to indicate that some action has been finished.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In fact, you probably use callbacks without even thinking about it.&lt;/p&gt;

&lt;p&gt;For instance, user events are asynchronous in nature, and you register callback functions that handle those events, like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const btn = document.querySelector("button");

btn.addEventListener("click", () =&amp;gt; {
  // Called when the user clicks the button
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The example code registers a callback to be executed when the user clicks the button. In the meantime, the program continues running other code and doesn't keep waiting for user input.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;📚 It's useful to know that the event handler code might not start executing &lt;strong&gt;immediately&lt;/strong&gt; after the user clicks the button. Learn about the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/EventLoop"&gt;event loop&lt;/a&gt; to understand why.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Problems with callbacks
&lt;/h3&gt;

&lt;p&gt;Callbacks are the most basic way to deal with asynchronous code. They can actually get you quite far, but at some point, they will start to feel limiting:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Callbacks create code-flow indirection because the function result is not returned but instead passed into a callback. This makes code harder to follow.&lt;/li&gt;
&lt;li&gt;Handling errors in callbacks is a matter of convention rather than API, which creates inconsistencies and cognitive load.&lt;/li&gt;
&lt;li&gt;Nested callbacks may lead to 'callback hell'. That's when callbacks are nested within other callbacks, several levels deep, often making the code hard to read and understand.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Consider this example of asynchronous JavaScript code using callbacks:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function makeTea(done) {
  const teapot = getTeapot();
  const kettle = getKettle();

  kettle.fill();

  kettle.boil((error, water) =&amp;gt; {
    if (error) {
      done(new Error('Kettle broke 😭'));
    } else { 
      kettle.pour(water, teapot);
      waitMinutes(5, () =&amp;gt; {
        const cup = getCup();
        const tea = teapot.pourInto(cup);
        waitMinutes(5, () =&amp;gt; {
            done(tea)
        });
      });
    }
  });

  // Executed right after putting on a kettle:
  addTeaLeaves(teapot);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's only 3 levels deep, but the nesting is already becoming excessive.&lt;/p&gt;

&lt;p&gt;The code isn't overly complicated, but it's already unpleasant to read, because of the nesting. Now consider that in real-world applications we need to deal with asynchronous code quite a bit, and you will realize why it soon feels like being in hell.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;😅 This pyramid shape that's formed by nesting callbacks is affectionately called &lt;strong&gt;'the pyramid of doom'&lt;/strong&gt;, because of the indentation that looks like a sideways pyramid.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Promises
&lt;/h2&gt;

&lt;p&gt;A Promise is a JavaScript object representing a value that will be available after an asynchronous operation completes. Promises can be returned synchronously like regular values, but the value may be supplied at a later point.&lt;/p&gt;

&lt;p&gt;It also provides an API to access the "promised" value by binding callbacks for different promise states.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const promise = new Promise((resolve, reject) =&amp;gt; {
  // This function runs an asyncronous operation that will call:
  // resolve(value) - if it succeeded, with the resolved value;
  // reject(reason) - if it failed, with the error set as value;
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Promise states
&lt;/h3&gt;

&lt;p&gt;Depending on the outcome of the asynchronous operation, promises can be in three states:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;pending:&lt;/em&gt; set initially, while the asynchronous operation is in progress;&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;fulfilled:&lt;/em&gt; the asynchronous operation has finished successfully;&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;rejected:&lt;/em&gt; the operation has failed.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;new Promise((resolve, reject) =&amp;gt; {
  setTimeout(() =&amp;gt; resolve("done!"), 1000);
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The promise is pending for 1 second, then it's fulfilled with the string value "done!".&lt;/p&gt;

&lt;p&gt;When a promise enters either fulfilled or rejected state it is said to be settled. The promise is formally said to be resolved if it is settled or resolved with a promise so that further resolving or rejecting it has no effect. However, colloquially it is often meant that the promise is fulfilled.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;📚 If you're interested in formal definitions, check out the &lt;a href="https://tc39.es/ecma262/#sec-promise-objects"&gt;ECMAScript specification&lt;/a&gt; and &lt;a href="https://promisesaplus.com/"&gt;Promise/A+ specification&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Working with promises
&lt;/h3&gt;

&lt;p&gt;A promise acts as a synchronous value - it can be passed as an argument or returned by functions as usual. However, to read its eventual value you need to "subscribe" to it. To allow that, promises have public methods:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;promise.then&lt;/code&gt; - is a primary method that accepts callbacks to run on success and failure;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;promise.catch&lt;/code&gt; - is a method to register callbacks for when the promise is rejected;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;promise.finally&lt;/code&gt; - is a method to register callbacks to be executed after the promise is fulfilled or rejected.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is how it looks in practice:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const promise = new Promise((resolve, reject) =&amp;gt; {
  // run async code
})

promise.then(
  (value) =&amp;gt; { /* handle a fulfilled promise result */ },
  (reason) =&amp;gt; { /* handle a rejected promise result */ }
)

promise.catch(
  (reason) =&amp;gt; { /* handle a rejected promise result */ },
)

promise.finally(
  () =&amp;gt; { /* handle a any result */ }
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As long as the promise is pending, the callbacks will not be executed. Once the promise has been resolved, it will always hold the result value. In case a handler is attached to a resolved handler, the handler simply runs right away and receives the promise value.&lt;/p&gt;

&lt;h3&gt;
  
  
  Promise chains
&lt;/h3&gt;

&lt;p&gt;A very useful feature of promises is that .then, .catch and .finally calls return promises, which means that we can attach multiple handlers by simply stringing the calls together:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const promise = new Promise((resolve, reject) =&amp;gt; {
  // handle async code
});

promise
  .then(handleFulfilledA, handleRejectedA)
  .then(handleFulfilledB)
  .then(handleFulfilledC, handleRejectedC)
  .catch(handleRejectedAny)
  .finally(handleResolved)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each &lt;code&gt;handleFulfilled&lt;/code&gt; handler will receive the result returned of calling the previous handler. In case an error is thrown in either hander, the promise will enter the rejected state and any further handlers called will be &lt;code&gt;handleRejected&lt;/code&gt; and &lt;code&gt;.catch&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note:&lt;/em&gt; a common beginner mistake is to attach multiple handlers on the original promise when trying to chain, it won't work, but it may be a useful feature in some cases:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const promise = new Promise((resolve, reject) =&amp;gt; {
  resolve(1);
});

promise.then((result) =&amp;gt; {
  console.log(result); // 1
  return result + 1;
});

promise.then((result) =&amp;gt; {
  console.log(result); // 1
  return result + 1;
});

promise.then((result) =&amp;gt; {
  console.log(result); // 1
  return result + 1;
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every .then call returns a new promise with the incremented value, but the handlers are attached to the original promise which was resolved with value 1.&lt;/p&gt;

&lt;p&gt;Remember our function that made tea? Let's see how it looks when rewritten to use promises:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function makeTea() {
  const teapot = getTeapot();
  const kettle = getKettle();

  kettle.fill();

  const teaPromise = kettle
    .boil() // Assuming boil function returns a promise
    .catch((error) =&amp;gt; {
      // Only handles kettle issues
      // Rethrows the error keep the rejected the promise state
      throw new Error("Kettle broke 😭");
    })
    .then(water =&amp;gt; {
      kettle.pour(water, teapot);
      return waitMinutes(5); // Assuming waitMinutes returns a promise
    }).then(() =&amp;gt; {
      const cup = getCup();
      const tea = teapot.pourInto(cup);
      return waitMinutes(5)
        .then(() =&amp;gt; tea); // Our promise chain must return the cup of tea
    });

  addTeaLeaves(teapot);

  return teaPromise;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Frankly, it's still not that pretty, but there's less nesting and it doesn't keep going deeper, because the promises are being chained onto the original promise for the most part.&lt;/p&gt;

&lt;h3&gt;
  
  
  Static methods
&lt;/h3&gt;

&lt;p&gt;Promises have a couple of static methods to help make working with them easier. The most important ones are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Promise.resolve(value)&lt;/code&gt; - creates a resolved promise with the provided value;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Promise.reject(reason)&lt;/code&gt; - creates a rejected promise with the provided value;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Promise.race([...promises])&lt;/code&gt; - creates a promise with the value of the first fulfilled or rejected promise in the provided array;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Promise.any([...promises])&lt;/code&gt; - creates a promise with the value of the first fulfilled promise in the array, if none are, then the promise is rejected.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Promise.all([...promises])&lt;/code&gt; - creates a promise that resolves to an array of the fulfilled promise values. If any promise in the array rejects, the returned promise is rejected.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Promise.allSettled([...promises])&lt;/code&gt; - creates a promise that's resolved when all of the promises in the array have been resolved (fulfilled or rejected). As a value, it receives an array of objects, that contain &lt;code&gt;status&lt;/code&gt; and &lt;code&gt;value&lt;/code&gt; or &lt;code&gt;reason&lt;/code&gt; properties, representing the outcomes of each promise.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To really understand how promises work, I recommend you to understand how they can be implemented. I guarantee that most frontend developers won't be able to implement promises, simply because they don't understand them.&lt;/p&gt;

&lt;p&gt;Well, now you will.&lt;/p&gt;

&lt;h2&gt;
  
  
  Implementing the Basic Promise API
&lt;/h2&gt;

&lt;p&gt;Promises are the foundation for doing asynchronous work in JavaScript, so it's imperative to understand them completely. When I was just beginning with JavaScript, some aspects of promises seemed magical. However, that only pointed to my incomplete understanding.&lt;/p&gt;

&lt;p&gt;The best way to dispel any magic is to build something from scratch. That way, we can understand how things work under the hood. Trust me when I say this - if you learn how to implement the promise API from scratch you will understand them better than most software developers.&lt;/p&gt;

&lt;p&gt;For our purposes, I'll call our promise Futurable, with otherwise the same API.&lt;/p&gt;

&lt;h3&gt;
  
  
  1) Tests
&lt;/h3&gt;

&lt;p&gt;Let's first start by writing some tests, so that we're sure we cover the complete API. We'll not spend time on this part, so if you're following along just copy-paste the code. We want to test at least these cases:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The promise can be resolved with a value;&lt;/li&gt;
&lt;li&gt;The promise can be rejected by calling &lt;code&gt;reject()&lt;/code&gt; or throwing an error;&lt;/li&gt;
&lt;li&gt;The promise can be rejected or resolved with another promise;&lt;/li&gt;
&lt;li&gt;Resolved and rejected promises can't be further rejected or resolved;&lt;/li&gt;
&lt;li&gt;Multiple &lt;code&gt;then()&lt;/code&gt;, &lt;code&gt;catch()&lt;/code&gt;, &lt;code&gt;finally()&lt;/code&gt; handlers can be chained;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;finally()&lt;/code&gt; must be invoked on either rejection or fulfillment.&lt;/li&gt;
&lt;li&gt;Promise operations should always be asynchronous;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Here's the test suite I will be using:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import Futurable from "./Futurable";

describe("Futurable &amp;lt;constructor&amp;gt;", () =&amp;gt; {
  it(`returns a promise-like object,
      that resolves it's chain after invoking &amp;lt;resolve&amp;gt;`, (done) =&amp;gt; {
    new Futurable&amp;lt;string&amp;gt;((resolve) =&amp;gt; {
      setTimeout(() =&amp;gt; {
        resolve("testing");
      }, 20);
    }).then((val) =&amp;gt; {
      expect(val).toBe("testing");
      done();
    });
  });

  it("is always asynchronous", () =&amp;gt; {
    let value = "no";
    new Futurable&amp;lt;string&amp;gt;((resolve) =&amp;gt; {
      value = "yes;";
      resolve(value);
    });
    expect(value).toBe("no");
  });

  it("resolves with the returned value", (done) =&amp;gt; {
    new Futurable&amp;lt;string&amp;gt;((resolve) =&amp;gt; resolve("testing")).then((val) =&amp;gt; {
      expect(val).toBe("testing");
      done();
    });
  });

  it("resolves a Futurable before calling &amp;lt;then&amp;gt;", (done) =&amp;gt; {
    new Futurable&amp;lt;string&amp;gt;((resolve) =&amp;gt;
      resolve(new Futurable((resolve) =&amp;gt; resolve("testing")))
    ).then((val) =&amp;gt; {
      expect(val).toBe("testing");
      done();
    });
  });

  it("resolves a Futurable before calling &amp;lt;catch&amp;gt;", (done) =&amp;gt; {
    new Futurable&amp;lt;string&amp;gt;((resolve) =&amp;gt;
      resolve(new Futurable((_, reject) =&amp;gt; reject("fail")))
    ).catch((reason) =&amp;gt; {
      expect(reason).toBe("fail");
      done();
    });
  });

  it("catches errors from &amp;lt;reject&amp;gt;", (done) =&amp;gt; {
    const error = new Error("Why u fail?");

    new Futurable((_, reject) =&amp;gt; {
      return reject(error);
    }).catch((err: Error) =&amp;gt; {
      expect(err).toBe(error);
      done();
    });
  });

  it("catches errors from &amp;lt;throw&amp;gt;", (done) =&amp;gt; {
    const error = new Error("Why u fail?");

    new Futurable(() =&amp;gt; {
      throw error;
    }).catch((err) =&amp;gt; {
      expect(err).toBe(error);
      done();
    });
  });

  it("does not change state anymore after promise is fulfilled", (done) =&amp;gt; {
    new Futurable((resolve, reject) =&amp;gt; {
      resolve("success");
      reject("fail");
    })
      .catch(() =&amp;gt; {
        done.fail(new Error("Should not be called"));
      })
      .then((value) =&amp;gt; {
        expect(value).toBe("success");
        done();
      });
  });

  it("does not change state anymore after promise is rejected", (done) =&amp;gt; {
    new Futurable((resolve, reject) =&amp;gt; {
      reject("fail");
      resolve("success");
    })
      .then(() =&amp;gt; {
        done.fail(new Error("Should not be called"));
      })
      .catch((err) =&amp;gt; {
        expect(err).toBe("fail");
        done();
      });
  });
});

describe("Futurable chaining", () =&amp;gt; {
  it("resolves chained &amp;lt;then&amp;gt;", (done) =&amp;gt; {
    new Futurable&amp;lt;number&amp;gt;((resolve) =&amp;gt; {
      resolve(0);
    })
      .then((value) =&amp;gt; value + 1)
      .then((value) =&amp;gt; value + 1)
      .then((value) =&amp;gt; value + 1)
      .then((value) =&amp;gt; {
        expect(value).toBe(3);
        done();
      });
  });

  it("resolves &amp;lt;then&amp;gt; chain after &amp;lt;catch&amp;gt;", (done) =&amp;gt; {
    new Futurable&amp;lt;number&amp;gt;(() =&amp;gt; {
      throw new Error("Why u fail?");
    })
      .catch(() =&amp;gt; {
        return "testing";
      })
      .then((value) =&amp;gt; {
        expect(value).toBe("testing");
        done();
      });
  });

  it("catches errors thrown in &amp;lt;then&amp;gt;", (done) =&amp;gt; {
    const error = new Error("Why u fail?");

    new Futurable((resolve) =&amp;gt; {
      resolve();
    })
      .then(() =&amp;gt; {
        throw error;
      })
      .catch((err) =&amp;gt; {
        expect(err).toBe(error);
        done();
      });
  });

  it("catches errors thrown in &amp;lt;catch&amp;gt;", (done) =&amp;gt; {
    const error = new Error("Final error");

    new Futurable((_, reject) =&amp;gt; {
      reject(new Error("Initial error"));
    })
      .catch(() =&amp;gt; {
        throw error;
      })
      .catch((err) =&amp;gt; {
        expect(err).toBe(error);
        done();
      });
  });

  it("short-circuits &amp;lt;then&amp;gt; chain on error", (done) =&amp;gt; {
    const error = new Error("Why u fail?");

    new Futurable(() =&amp;gt; {
      throw error;
    })
      .then(() =&amp;gt; {
        done.fail(new Error("Should not be called"));
      })
      .catch((err) =&amp;gt; {
        expect(err).toBe(error);
        done();
      });
  });

  it("passes value through undefined &amp;lt;then&amp;gt;", (done) =&amp;gt; {
    new Futurable((resolve) =&amp;gt; {
      resolve("testing");
    })
      .then()
      .then((value) =&amp;gt; {
        expect(value).toBe("testing");
        done();
      });
  });

  it("passes value through undefined &amp;lt;catch&amp;gt;", (done) =&amp;gt; {
    const error = new Error("Why u fail?");

    new Futurable((_, reject) =&amp;gt; {
      reject(error);
    })
      .catch()
      .catch((err) =&amp;gt; {
        expect(err).toBe(error);
        done();
      });
  });
});

describe("Futurable &amp;lt;finally&amp;gt;", () =&amp;gt; {
  it("it is called when Futurable is resolved", (done) =&amp;gt; {
    new Futurable((resolve) =&amp;gt; resolve("success")).finally(() =&amp;gt; {
      done();
    });
  });

  it("it is called when Futurable is rejected", (done) =&amp;gt; {
    new Futurable((_, reject) =&amp;gt; reject("fail")).finally(() =&amp;gt; {
      done();
    });
  });

  it("it preserves a resolved promise state", (done) =&amp;gt; {
    let finallyCalledTimes = 0;

    new Futurable((resolve) =&amp;gt; resolve("success"))
      .finally(() =&amp;gt; {
        finallyCalledTimes += 1;
      })
      .then((value) =&amp;gt; {
        expect(value).toBe("success");
        expect(finallyCalledTimes).toBe(1);
        done();
      });
  });

  it("it preserves a rejected promise state", (done) =&amp;gt; {
    let finallyCalledTimes = 0;

    new Futurable((_, reject) =&amp;gt; reject("fail"))
      .finally(() =&amp;gt; {
        finallyCalledTimes += 1;
      })
      .catch((reason) =&amp;gt; {
        expect(reason).toBe("fail");
        expect(finallyCalledTimes).toBe(1);
        done();
      });
  });
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;👉 If you want to follow along, feel free to create a &lt;a href="https://codesandbox.io/"&gt;typescript codesandbox&lt;/a&gt; and paste this code. Or &lt;a href="https://codesandbox.io/s/futurable-codefrontend-com-glt0qq?file=/src/Futurable.spec.ts"&gt;fork mine&lt;/a&gt; and delete the Futurable.ts file if you want to start fresh. Switch to "Tests" tab to see the results.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  2) The interface
&lt;/h3&gt;

&lt;p&gt;Now we move on to the implementation, and the first thing we need to do is to define the public API.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class Futurable&amp;lt;T&amp;gt; {
  constructor(
    executor: (
      resolve: (value: T | Futurable&amp;lt;T&amp;gt;) =&amp;gt; void,
      reject: (reason?: any) =&amp;gt; void
    ) =&amp;gt; void
  ) {
    // TODO: implement
  }

  then = &amp;lt;R1 = T, R2 = never&amp;gt;(
    onFulfilled?: (value: T) =&amp;gt; R1 | Futurable&amp;lt;R1&amp;gt;,
    onRejected?: (reason: any) =&amp;gt; R2 | Futurable&amp;lt;R2&amp;gt;
  ) =&amp;gt; {
    // TODO: implement
  };

  catch = &amp;lt;R = never&amp;gt;(onRejected?: (reason: any) =&amp;gt; R | Futurable&amp;lt;R&amp;gt;) =&amp;gt; {
    // TODO: implement
  };

  finally = (onFinally: () =&amp;gt; void): Futurable&amp;lt;T&amp;gt; =&amp;gt; {
    // TODO: implement
  };
}

export default Futurable&amp;lt;T&amp;gt;;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I took the types mostly from the ES6 promise type definitions so that our implementation gets as close to the standard as possible.&lt;/p&gt;

&lt;p&gt;Our constructor will take the callback as a parameter and call it passing &lt;code&gt;resolve&lt;/code&gt; and &lt;code&gt;reject&lt;/code&gt; functions.&lt;/p&gt;

&lt;p&gt;Remember how I mentioned that &lt;code&gt;then()&lt;/code&gt; accepts callbacks for both fulfillment and rejection? Well, that's what we define here. It's going to be the basis for registering our handlers - catch and finally is only 'sugar', as you will see later.&lt;/p&gt;

&lt;h3&gt;
  
  
  3) State machine
&lt;/h3&gt;

&lt;p&gt;I've already mentioned how a promise has 3 states: &lt;em&gt;fulfilled, rejected,&lt;/em&gt; and &lt;em&gt;pending&lt;/em&gt;. This can be expressed as a &lt;a href="https://developer.mozilla.org/en-US/docs/Glossary/State_machine"&gt;state machine&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--TX5R7MS7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1663142811135/Vw6JdJ-gK.png%2520align%3D%2522left%2522" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--TX5R7MS7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1663142811135/Vw6JdJ-gK.png%2520align%3D%2522left%2522" alt="image.png" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The promise starts off as &lt;em&gt;pending&lt;/em&gt; and moves into &lt;em&gt;resolved&lt;/em&gt; state or rejected state. After it makes the transition, it can no longer be &lt;em&gt;resolved, rejected,&lt;/em&gt; or enter the &lt;em&gt;pending&lt;/em&gt; state.&lt;/p&gt;

&lt;p&gt;To implement this, first, we need to define the internal state and the result of the promise, let's do that:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;enum FuturableState {
  Pending,
  Resolved,
  Rejected
}

class Futurable&amp;lt;T&amp;gt; {
  private state = FuturableState.Pending;
  private result?: any;

  // ...
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we can implement a function that handles these transitions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const isThenable = (obj: any): obj is Futurable&amp;lt;any&amp;gt; =&amp;gt;
  typeof obj?.then === "function";

class Futurable&amp;lt;T&amp;gt; {
  // ...

  private resolve = (value: T | Futurable&amp;lt;T&amp;gt;) =&amp;gt; {
    // TODO: implement
  };

  private reject = (reason?: any) =&amp;gt; {
    // TODO: implement
  };

  private setResult = (value: any, state: FuturableState) =&amp;gt; {
    if (this.state !== FuturableState.Pending) {
      return;
    }

    if (isThenable(value)) {
      value.then(this.resolve, this.reject);
      return;
    }

    this.state = state;
    this.result = value;
  };
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;setResult&lt;/code&gt; method is now responsible for making a transition and setting the promise result, let's understand what the code does.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;We only need to allow transitions from &lt;em&gt;pending&lt;/em&gt; state, otherwise, calling &lt;code&gt;setResult&lt;/code&gt; will do nothing, so we exit the function by returning.&lt;/li&gt;
&lt;li&gt;We check if the value provided was in itself a promise and resolve it instead of transitioning the state. We also defined the &lt;code&gt;resolve&lt;/code&gt; and &lt;code&gt;reject&lt;/code&gt; internal functions, which we'll implement later.&lt;/li&gt;
&lt;li&gt;If the value was not a promise, we transition the state and value.&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;📌 According to the promise standard, if an object contains a &lt;code&gt;then&lt;/code&gt; method, then it should act like a promise, even if it isn't an instance of a &lt;code&gt;Promise&lt;/code&gt; class - it's called a &lt;strong&gt;thenable&lt;/strong&gt;. Now that's pretty cool! That means, that we could resolve &lt;code&gt;Futurable&lt;/code&gt; with new &lt;code&gt;Promise(...)&lt;/code&gt; as a result and it would still work, and vice versa.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  4) Resolve / Reject
&lt;/h3&gt;

&lt;p&gt;Now that we have a function that handles our promise's state transitions, we can use it to implement the constructor and resolve/reject functions. It's as simple as calling our &lt;code&gt;setResult&lt;/code&gt; function in &lt;code&gt;resolve&lt;/code&gt; and &lt;code&gt;reject&lt;/code&gt; function and then using them in our constructor:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  constructor(
    executor: (
      resolve: (value: T | Futurable&amp;lt;T&amp;gt;) =&amp;gt; void,
      reject: (reason?: any) =&amp;gt; void
    ) =&amp;gt; void
  ) {
      executor(this.resolve, this.reject);
    } catch (e) {
      this.reject(e);
    }
  }

  // ...

  private resolve = (value: T | Futurable&amp;lt;T&amp;gt;) =&amp;gt; {
    this.setResult(value, FuturableState.Resolved);
  };

  private reject = (reason?: any) =&amp;gt; {
    this.setResult(reason, FuturableState.Rejected);
  };
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You may notice the try-catch block and wonder why we need it in the constructor. That's because calling &lt;code&gt;reject&lt;/code&gt; is not the only way to reject a promise, we can also &lt;code&gt;throw&lt;/code&gt; an error. Doing that will trigger our catch block, and we handle the error by rejecting the promise.&lt;/p&gt;

&lt;p&gt;Now we have the ability to create a new &lt;code&gt;Futurable&lt;/code&gt; promise and run the callback. Resolving or rejecting it in the callback will change the internal promise state and set the value:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const resolvedPromise = new Futurable((resolve, reject) =&amp;gt; {
  resolve('success!')
})

const rejectedPromise = new Futurable((resolve, reject) =&amp;gt; {
  reject('fail...')
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, there's one issue...&lt;/p&gt;

&lt;h3&gt;
  
  
  5) Executing promises asynchronously
&lt;/h3&gt;

&lt;p&gt;Constructing a new promise will immediately execute the callback. This means that our Promises are blocking the code execution, which means they're not actually asynchronous operations.&lt;/p&gt;

&lt;p&gt;If you want to see the problem in action, run this code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;let called = false;

new Futurable((resolve) =&amp;gt; {
  called = true;
  resolve();
});

console.log(called); // Prints: "true"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The constructor is being run synchronously, asynchronous code would not run the callback immediately.&lt;/p&gt;

&lt;p&gt;Let's fix that.&lt;/p&gt;

&lt;p&gt;Without going deep into how the event loop works, we should at least know that our code is being run synchronously in these phases:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Executing tasks - your code;&lt;/li&gt;
&lt;li&gt;Executing jobs - native ES6 Promise callbacks;&lt;/li&gt;
&lt;li&gt;Executing messages - events, callbacks, ajax requests, etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you want a thorough explanation of how the event loop works, watch this excellent presentation:&lt;/p&gt;

&lt;p&gt;%[&lt;a href="https://www.youtube.com/watch?v=8aGhZQkoFbQ"&gt;https://www.youtube.com/watch?v=8aGhZQkoFbQ&lt;/a&gt;]&lt;/p&gt;

&lt;p&gt;What this means in practice is that your code is run synchronously at the highest priority - as long as it's running, it will block the execution of any code that follows. When the code execution phase is over, it will process any jobs and messages that have been received in the meanwhile.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;😉 If you want to see what I mean by blocking code, run &lt;code&gt;(true) { console.log('blocking'); console.log('not blocking'); }&lt;/code&gt; in your browser console for example. You will never see the message 'not blocking'. Do it at your own peril though, you may not be able to close the tab anymore and may have to kill the browser.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Since we're doing a custom implementation of the promises, we assume that there's no native support for Promises, but we still need to execute the &lt;code&gt;Futurable&lt;/code&gt; callbacks asynchronously. To do that we can utilize a well-known hack: &lt;code&gt;setTimeout(callback, 0);&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This would delegate the execution of the callback to run immediately after any synchronous code, hence zero milliseconds. Let's write a utility function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const runAsync = (callback: () =&amp;gt; void) =&amp;gt; {
  setTimeout(callback, 0);
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can now wrap our constructor and execute code with this utility to run them asynchronously as such:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// ...

constructor(
  executor: (
    resolve: (value: T | Futurable&amp;lt;T&amp;gt;) =&amp;gt; void,
    reject: (reason?: any) =&amp;gt; void
  ) =&amp;gt; void
) {
  runAsync(() =&amp;gt; {
    // ...
  });
}

private setResult = (value: any, state: FuturableState) =&amp;gt; {
  runAsync(() =&amp;gt; {
    // ...
  }
};

// ...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you test the previous example again, you will see that it prints false, which means that the promise callback code isn't run immediately and doesn't block the code execution anymore.&lt;/p&gt;

&lt;h3&gt;
  
  
  6) Executing handlers
&lt;/h3&gt;

&lt;p&gt;Promises allow us to access their value by attaching &lt;code&gt;then&lt;/code&gt; or &lt;code&gt;catch&lt;/code&gt; handlers and providing them with callbacks which then receive value asynchronously. Because the callbacks are supposed to be executed one by one sequentially, we can put them in a queue.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;type Handler&amp;lt;T&amp;gt; = {
  handleThen: (value: T) =&amp;gt; void;
  handleCatch: (reason?: any) =&amp;gt; void;
};

export default class Futurable&amp;lt;T&amp;gt; {
  private handlers: Handler&amp;lt;T&amp;gt;[] = [];

  // ...
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;How this is going to work:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Whenever &lt;code&gt;.then&lt;/code&gt; or &lt;code&gt;.catch&lt;/code&gt; is called, we'll push the callback handler into a queue. There will always be a handler for both, except one of them will simply pass the promise value through as a result, like this &lt;code&gt;(value) =&amp;gt; value&lt;/code&gt;. This will ensure, that the whole chain of handlers gets executed, but irrelevant handlers are "skipped", e.g. skip all &lt;code&gt;.catch&lt;/code&gt; calls in case there was no error.&lt;/li&gt;
&lt;li&gt;We will execute all of the handlers when the promise is fulfilled or rejected.&lt;/li&gt;
&lt;li&gt;We will execute the resolvers as soon as a handler is pushed into the queue, in case the handler is attached to the promise that has already been resolved. However, we should remember not to execute the handlers until the promise has resolved.&lt;/li&gt;
&lt;li&gt;We will remove all handlers as soon as they finished executing.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let's write the function to execute the handlers first:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;private executeResolvers = () =&amp;gt; {
  if (this.state === FuturableState.Pending) {
    return;
  }

  this.handlers.forEach((resolver) =&amp;gt; {
    if (this.state === FuturableState.Resolved) {
      resolver.handleThen(this.result);
    } else {
      resolver.handleCatch(this.result);
    }
  });

  this.handlers = [];
};

private setResult = (value: any, state: FuturableState) =&amp;gt; {
  // ...
  this.executeResolvers();
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;First, we check if the promise has resolved already, if it hasn't we skip it. We only want to execute .then and .catch handlers only on resolved promises.&lt;/p&gt;

&lt;p&gt;Then we run all of the handlers for &lt;code&gt;.then&lt;/code&gt; or &lt;code&gt;.catch&lt;/code&gt; depending on whether the promise is resolved or rejected. Afterward, we clean all of the handlers so that they don't get executed again.&lt;/p&gt;

&lt;p&gt;Finally, we need to run the resolvers as soon as we set the result of the promise, which will execute the promise chain.&lt;/p&gt;

&lt;h3&gt;
  
  
  7) Implementing &lt;em&gt;.then&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;We can run the handlers, but we still need a way to push the handlers to the queue. That's where &lt;code&gt;.then&lt;/code&gt; handler comes in:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;then = &amp;lt;R1 = T, R2 = never&amp;gt;(
  onFulfilled?: null | ((value: T) =&amp;gt; R1 | Futurable&amp;lt;R1&amp;gt;),
  onRejected?: null | ((reason: any) =&amp;gt; R2 | Futurable&amp;lt;R2&amp;gt;)
) =&amp;gt; {
  return new Futurable&amp;lt;R1 | R2&amp;gt;((resolve, reject) =&amp;gt; {
    this.resolvers.push({
      handleThen: (value) =&amp;gt; {
        if (!onFulfilled) {
          resolve(value as any);
        } else {
          try {
            resolve(onFulfilled(value) as R1 | Futurable&amp;lt;R1 | R2&amp;gt;);
          } catch (e) {
            reject(e);
          }
        }
      },
      handleCatch: (reason) =&amp;gt; {
        if (!onRejected) {
          reject(reason);
        } else {
          try {
            resolve(onRejected(reason) as R2 | Futurable&amp;lt;R1 | R2&amp;gt;);
          } catch (e) {
            reject(e);
          }
        }
      }
    });
    this.executeResolvers();
  });
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The code looks daunting, but it is actually pretty simple when broken down.&lt;/p&gt;

&lt;p&gt;By specification, &lt;code&gt;.then&lt;/code&gt; is supposed to be able to handle both fulfill and reject callbacks, and the types come directly from the ES6 &lt;code&gt;Promise&lt;/code&gt; interface. The handlers must always return a promise so that they can be chained, so as a result, we return a new &lt;code&gt;Futurable&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We push &lt;code&gt;.then&lt;/code&gt; and &lt;code&gt;.catch&lt;/code&gt; handlers, that are basically identical, except one is calling the resolve callback, and the other one - reject.&lt;/p&gt;

&lt;p&gt;We resolve the promise with the result returned from the callback. In case the callback is not provided, we simply pass through the original value of the promise, which allows us to chain promises even if we omit either handler, essentially replacing it with &lt;code&gt;(value) =&amp;gt; value&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Then we wrap everything in try/catch, because we should be able to reject the promise by throwing an error in the handler, as an alternative to calling &lt;code&gt;reject&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Finally, as mentioned earlier, we need to execute the resolvers after adding pushing the promise into the queue, so that if the promise was already resolved, the new handler would still run.&lt;/p&gt;

&lt;p&gt;Let's test:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;new Futurable((resolve) =&amp;gt; resolve("ok"))
  .then((value) =&amp;gt; {
    console.log(value);
    throw new Error("fail");
  })
  .then(null, (error) =&amp;gt; console.log(error.message));
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you run this code, you should see both &lt;code&gt;ok&lt;/code&gt; and &lt;code&gt;fail&lt;/code&gt;, on the screen, which means that our &lt;code&gt;Futurable&lt;/code&gt; promise is chainable and can handle both fulfillment and rejection.&lt;/p&gt;

&lt;h3&gt;
  
  
  8) Implementing &lt;em&gt;.catch&lt;/em&gt; and &lt;em&gt;.finally&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;We already have a fully functional Promise now, but let's add some sugar: &lt;code&gt;.catch&lt;/code&gt; and &lt;code&gt;.finally&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;From the above test, you can see, that &lt;code&gt;catch&lt;/code&gt; is equivalent to &lt;code&gt;then&lt;/code&gt; without the &lt;code&gt;onFulfill&lt;/code&gt; handler:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;catch = &amp;lt;R = never&amp;gt;(onRejected?: (reason: any) =&amp;gt; R | Futurable&amp;lt;R&amp;gt;) =&amp;gt; {
  return this.then(null, onRejected);
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And &lt;code&gt;.finally&lt;/code&gt; is as simple as executing a callback no matter if the promise was fulfilled or rejected:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;finally = (onFinally: () =&amp;gt; void): Futurable&amp;lt;T&amp;gt; =&amp;gt; {
  return this.then(
    (value) =&amp;gt; {
      onFinally();
      return value;
    },
    (reason) =&amp;gt; {
      onFinally();
      throw reason;
    }
  );
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The only caveat is that &lt;code&gt;.finally&lt;/code&gt; must not change the promise status, so it passes through whatever the result was - it returns the value if the promise was resolved or rethrows the error in case it was rejected.&lt;/p&gt;

&lt;p&gt;You can see the full implementation here:&lt;/p&gt;

&lt;p&gt;%[&lt;a href="https://codesandbox.io/embed/futurable-codefrontend-com-glt0qq?fontsize=14&amp;amp;hidenavigation=1&amp;amp;theme=dark"&gt;https://codesandbox.io/embed/futurable-codefrontend-com-glt0qq?fontsize=14&amp;amp;hidenavigation=1&amp;amp;theme=dark&lt;/a&gt;]&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;There we have it&lt;/strong&gt; - the basic premise implementation we built ourselves. As a fun experiment, try to use it interchangeably with the native promise and see if it works. If you wish to refine the implementation further and deepen the understanding of promises, try to implement these static methods:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Promise.resolve&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Promise.reject&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Promise.race&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Promise.any&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Promise.all&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Promise.allSettled&lt;/code&gt; if you really want to go &lt;em&gt;advanced&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Async/await
&lt;/h2&gt;

&lt;p&gt;By now you might have gathered, that promises solve some of the issues of working with asynchronous operations in JavaScript, yet they're not perfect:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;They don't completely eliminate the nesting;&lt;/li&gt;
&lt;li&gt;Their readability is not great;&lt;/li&gt;
&lt;li&gt;While the promise can be returned synchronously, its result can't be accessed synchronously;&lt;/li&gt;
&lt;li&gt;Regular language constructs are not straightforward to use (e.g. try/catch block).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Well, recently a more convenient way of handling asynchronous operations was introduced - &lt;em&gt;async/await&lt;/em&gt;, and promises are the heart of it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Async functions
&lt;/h3&gt;

&lt;p&gt;When declaring a function, we can mark it as async, which will allow us to return any value the same as always, but the result would automatically be considered a promise:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;async function doAsyncStuff() {
  return 1;
}

const promise = doAsyncStuff()
  .then((result) =&amp;gt; console.log(result)) // Prints: 1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As we see in the example, returning a value is equivalent to resolving a promise. Even if there's no value returned, the result will still be a promise, except with &lt;code&gt;undefined&lt;/code&gt; as the result. Similarly, throwing an error is equivalent to rejecting the promise:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Inline functions can also be async
const doAsyncStuff = async () =&amp;gt; {
  throw new Error("don't wanna");
}

const promise = doAsyncStuff()
  .catch((error) =&amp;gt; console.log(error.message)) // Prints: "don't wanna"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Await
&lt;/h3&gt;

&lt;p&gt;What's cool about async functions, is that inside of them you can use the &lt;code&gt;await&lt;/code&gt; keyword to synchronously resolve promises:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;async function doAsyncStuff() {
  return 1;
}

const timeoutPromise = new Promise((resolve, reject) =&amp;gt; {
  setTimeout(() =&amp;gt; resolve("done!"), 1000);
});

async function useAsyncStuff() {
  const asyncStuff = await doAsyncStuff();
  const timeoutResult = await timeoutPromise();
  console.log(asyncStuff, timeoutResult); // Prints: "1 done!"
}

useAsyncStuff();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;await&lt;/code&gt; keyword makes the code blocking until the promise is resolved, essentially waiting for the operation to complete until it proceeds with code execution. This allows us to get results from asynchronous functions in much the same way as regular ones.&lt;/p&gt;

&lt;p&gt;But that's not it. When you use &lt;code&gt;await&lt;/code&gt; the error will be thrown synchronously as well, so the regular try/catch block will work:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;async function doAsyncStuff() {
  throw new Error("Ah damn...");
}

async function useAsyncStuff() {
  try {
    await doAsyncStuff();
  } catch(err) {
    console.log(err); // Prints: "Ah damn..."
  }
}

useAsyncStuff();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, in the end, it's all promises, so async/await can be used with &lt;code&gt;.then&lt;/code&gt;, &lt;code&gt;.catch&lt;/code&gt; and &lt;code&gt;.finally&lt;/code&gt; interchangeably:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;async function doAsyncStuff() {
  throw new Error("Ah damn...");
}

async function useAsyncStuff() {
  await doAsyncStuff().catch(() =&amp;gt; {
    console.log(err); // Prints: "Ah damn..."
  });
}

useAsyncStuff();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As a final exercise, let's rewrite our tea preparation function using async/await:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;async function makeTea() {
  const teapot = getTeapot();
  const kettle = getKettle();

  kettle.fill();

  const hotWaterPromise = kettle.boil().catch(() =&amp;gt; {
    throw new Error("Kettle broke 😭");
  });

  // Add tea leaves while we wait for the water to boil, like previously
  const [water] = await Promise.all([
    hotWaterPromise,
    addTeaLeaves(teapot)
  ]);

  kettle.pour(water, teapot);
  await waitMinutes(5);

  const cup = getCup();
  const tea = teapot.pourInto(cup);

  await waitMinutes(5);

  return tea;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you see async/await has eliminated excessive nesting and is generally simpler to read and understand.&lt;/p&gt;

&lt;h3&gt;
  
  
  Caveat
&lt;/h3&gt;

&lt;p&gt;As you can imagine, async/await solves most of the remaining issues with promises. However, there are some common mistakes that beginners run into.&lt;/p&gt;

&lt;p&gt;You can't use &lt;code&gt;await&lt;/code&gt; at the root level or regular functions, only in async functions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function doAsyncStuff() {
  const promise = Promise.resolve("done!");
  const result = await promise; // Syntax error
}

const result = await new Promise((resolve) =&amp;gt; resolve("done!")); // Syntax error
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Although, some modern JavaScript runtimes (modern browsers, latest node versions) allow async at the root level. As a workaround for older JS runtimes, wrap the call in a self-invoking anonymous async function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;(async () =&amp;gt; {
  const result = await new Promise((resolve) =&amp;gt; resolve("done!")); // Works
})();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Final thoughts
&lt;/h2&gt;

&lt;p&gt;Modern JavaScript provides ways to work with asynchronous operations conveniently. However, promises are the basis of everything that's async in JavaScript, so it's essential to understand them completely.&lt;/p&gt;

&lt;p&gt;I've shown how you would implement promises yourself and hopefully, the process has shown you that there's no magic involved when you break them down.&lt;/p&gt;

&lt;p&gt;If it was your first involvement with promises, you might have gotten a bit overwhelmed, but don't worry, with practice, using promises will become second nature, and you can always use this post as a reference if you want to revisit the implementation with fresh eyes after a while.&lt;/p&gt;




&lt;p&gt;This article is reposted from my blog at &lt;a href="https://codefrontend.com/promises"&gt;codefrontend.com&lt;/a&gt;, check it out for other deep dives and quick guides. Follow me on Twitter &lt;a href="https://twitter.com/VincasStonys"&gt;@VincasStonys&lt;/a&gt; for web development tips.&lt;/p&gt;

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