<?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: Raymond </title>
    <description>The latest articles on DEV Community by Raymond  (@raymondg).</description>
    <link>https://dev.to/raymondg</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%2F2825908%2F7f77b786-0d2f-44a4-a75e-118cc2045852.png</url>
      <title>DEV Community: Raymond </title>
      <link>https://dev.to/raymondg</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/raymondg"/>
    <language>en</language>
    <item>
      <title>Asynchronous Javascript</title>
      <dc:creator>Raymond </dc:creator>
      <pubDate>Tue, 29 Apr 2025 17:02:50 +0000</pubDate>
      <link>https://dev.to/raymondg/asynchronous-javascript-3ked</link>
      <guid>https://dev.to/raymondg/asynchronous-javascript-3ked</guid>
      <description>&lt;h2&gt;
  
  
  What is synchronous javascript?
&lt;/h2&gt;

&lt;p&gt;When talking about javascript, you may have come across a term called the javascript interpreter or javascript engine. If you haven't, the interpreter is basically just your browser and how it reads and evaluates javascript (or &lt;strong&gt;node&lt;/strong&gt; if executing javascript on the server). The interpreter parses (fancy word for "reads") your javascript code in a top down order. Think of this in the same way you would read a book. You start reading (at least in most languages) from left to right and top to bottom.&lt;/p&gt;

&lt;p&gt;Consider this code snippet:&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;hello&lt;/span&gt;&lt;span class="dl"&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;world&lt;/span&gt;&lt;span class="dl"&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;!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;// hello&lt;/span&gt;
&lt;span class="c1"&gt;// world&lt;/span&gt;
&lt;span class="c1"&gt;// !&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In javascript, the next line of code will not be allowed to run until the previous line has completed and this is referred to as  blocking code. So in our example, the log for &lt;code&gt;'world'&lt;/code&gt; will not run before the log &lt;code&gt;'hello'&lt;/code&gt; because of its order.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is asynchronous javascript?
&lt;/h2&gt;

&lt;p&gt;Asynchronous javascript is code that can run out of order of the original flow of code.&lt;/p&gt;

&lt;p&gt;Consider this snippet:&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;hello&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;setTimeout&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;world&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;1000&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;!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;// hello&lt;/span&gt;
&lt;span class="c1"&gt;// !&lt;/span&gt;
&lt;span class="c1"&gt;// world&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;setTimeout&lt;/code&gt; is an asynchronous function that takes a function as an argument (a &lt;strong&gt;callback&lt;/strong&gt;) and a time (in milliseconds) that will act as the amount of time to wait until it can execute the callback passed.&lt;/p&gt;

&lt;p&gt;Looking at the example, the interpreter starts to parse the code from top to bottom. It first logs &lt;code&gt;hello&lt;/code&gt; to the console. It moves on to the next line of code and sees that there is a &lt;code&gt;setTimeout&lt;/code&gt; which is asynchronous. It determines that we don't need to wait for this line to finish. It registers this callback in a different queue for execution (beyond the scope of this article), so we can move on to the next line to execute. It then logs the &lt;code&gt;!&lt;/code&gt; to the console. Now, at minimum 1000 milliseconds (1 second) has passed. It can now execute the callback in &lt;code&gt;setTimeout&lt;/code&gt; and logs &lt;code&gt;world&lt;/code&gt; to the console.&lt;/p&gt;

&lt;p&gt;Asynchronous code is non-blocking, meaning that the interpreter doesn't have to wait for the async code to execute for it to move to the next line for processing. Think of it like asking someone on a date when you were in high school (might be showing my age here). You say on a note something along the lines of "Will you go out with me?" and a few boxes that say &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[] yes ✅&lt;/li&gt;
&lt;li&gt;[] no ❌&lt;/li&gt;
&lt;li&gt;[] maybe ❓&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You pass it off to that person and and go about your day until they give it back with a reply (and hopefully you didn't get rejected 😬). This is, in effect, an asynchronous operation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Callbacks
&lt;/h2&gt;

&lt;p&gt;To understand what a callback is, you have to understand that functions can take in arguments. These arguments can be any javascript type including other functions. At first, callbacks can be a bit tedious to understand, but once it clicks... you'll have a much easier time with programming in javascript.&lt;/p&gt;

&lt;h3&gt;
  
  
  Function declarations and expressions
&lt;/h3&gt;

&lt;p&gt;There are a few ways to declare a function. One is called a &lt;strong&gt;function declaration&lt;/strong&gt; where you use the &lt;code&gt;function&lt;/code&gt; keyword.&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;doSomething&lt;/span&gt;&lt;span class="p"&gt;(){}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The other is a &lt;strong&gt;function expression&lt;/strong&gt; where it is declared as a variable with &lt;code&gt;let&lt;/code&gt;, &lt;code&gt;var&lt;/code&gt;, or &lt;code&gt;const&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;const&lt;/span&gt; &lt;span class="nx"&gt;doSomething&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(){}&lt;/span&gt;
&lt;span class="c1"&gt;//or&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;doSomething&lt;/span&gt; &lt;span class="o"&gt;=&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Parameters can be added to the function to be used as arguments. To be a parameter is when a function declaration or expression is being created (defined).&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;// they are **parameters** during function declaration&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;param1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nx"&gt;param2&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;param1&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;param2&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To be an argument is when the function is being invoked (called).&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;// they are **arguments** when the function is called&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;arg1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;arg2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;
&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arg1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nx"&gt;arg2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// 4&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Think of parameters as local variables to the function. Whatever is passed as an argument becomes the value of the parameter that was defined. Essentially a placeholder until the function is invoked.&lt;/p&gt;

&lt;h3&gt;
  
  
  Defining a function with a callback
&lt;/h3&gt;

&lt;p&gt;Why is it important to know about function declarations and function expressions? That is where you will understand how a callback is created and how arguments are passed to them.&lt;/p&gt;

&lt;p&gt;When you declare (define) your function you can add a &lt;strong&gt;callback&lt;/strong&gt; parameter to the function that can be used.&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;doSomething&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
  &lt;span class="nf"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hello world&lt;/span&gt;&lt;span class="dl"&gt;'&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 the snippet above, we are creating a &lt;code&gt;doSomething&lt;/code&gt; function declaration. The parameter (&lt;code&gt;callback&lt;/code&gt;) is expected to be a function. Here, we've named it &lt;code&gt;callback&lt;/code&gt; but could be any name you decide to give it. In the &lt;code&gt;doSomething&lt;/code&gt; function body we are calling the passed callback function with a string value as an argument (&lt;code&gt;'hello world'&lt;/code&gt;). Now we can use the &lt;code&gt;doSomething&lt;/code&gt; function and pass in a callback function as an argument.&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;// hello could be changed to anything&lt;/span&gt;
&lt;span class="nf"&gt;doSomething&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;hello&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="nx"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// "hello world"&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Since the string was passed as an argument to the &lt;code&gt;callback&lt;/code&gt; function we can use that value inside of the callback function's body. We simply log the &lt;code&gt;hello&lt;/code&gt; argument to the console which logs the string &lt;code&gt;"hello world"&lt;/code&gt;. The &lt;code&gt;hello&lt;/code&gt; variable can be named anything you want to name it. It is important to understand here that the value of that argument, in this context, will always evaluate to the string provided in the &lt;code&gt;doSomething&lt;/code&gt; function definition's callback (&lt;code&gt;"hello world"&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;This understanding in callbacks can help you better understand that when some library documents a callback and has arguments to them, there isn't much "magic" actually happening. Somewhere in the function definition someone wrote code to pass an argument to that callback. That argument (or arguments) will always be the same object, number, boolean, or whatever it may be. Though the values may change, the expected type typically won't.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Old Ways
&lt;/h2&gt;

&lt;p&gt;At some point during the evolution of development, async code was typically handled through a series of callbacks. This created readability issues especially when you started deeply nesting callbacks for asynchronous operations:&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;doSomething&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;doSomethingElse&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="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value2&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;doSomethingMore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value2&lt;/span&gt;&lt;span class="p"&gt;,(&lt;/span&gt;&lt;span class="nx"&gt;endResult&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="nx"&gt;endResult&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Based on the example above imagine that you had some operation that you had to perform where you couldn't complete some task until multiple other tasks were completed before it. This would force you to nest your functions as in the example. If you have 5-10 tasks that need to be completed and calculations that needed to be performed on some of them before passing them on, this could get pretty messy pretty quickly.&lt;/p&gt;

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

&lt;p&gt;Promises were introduced in ES6 of javascript in 2015. This simplified async operations by providing a more readable way to handle callbacks using method chaining. Some of the methods for the &lt;code&gt;Promise&lt;/code&gt; object are &lt;code&gt;.then()&lt;/code&gt;, &lt;code&gt;.catch()&lt;/code&gt; and &lt;code&gt;.finally()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If you wanted to define a function as a promise we would need to return a promise from 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;function&lt;/span&gt; &lt;span class="nf"&gt;valueAfter2Seconds&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="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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;10&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;2000&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the example, we are defining a function &lt;code&gt;valueAfter2Seconds&lt;/code&gt;. In the function body we are calling &lt;code&gt;new Promise&lt;/code&gt; and returning it. The promise constructor takes a callback function. The arguments to the callback are &lt;code&gt;resolve&lt;/code&gt; and &lt;code&gt;reject&lt;/code&gt;. Both are callback functions as well. We are creating a delay of 2 seconds and resolve with a value of &lt;code&gt;10&lt;/code&gt;. Whatever value you would like to resolve gets passed as the argument to the resolve callback. Likewise, if using the &lt;code&gt;reject&lt;/code&gt; callback, it will raise an error with the rejected value passed to it.&lt;/p&gt;

&lt;p&gt;Now we can see how to get the value from the promise.&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;valueAfter2Seconds&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;value&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;value&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
  &lt;span class="c1"&gt;// 10 &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When &lt;code&gt;valueAfter2seconds&lt;/code&gt; runs, it immediately returns a &lt;code&gt;promise&lt;/code&gt;. The state of that promise during initial execution is pending. The &lt;code&gt;.then&lt;/code&gt; method waits for the resolved value from the promise. &lt;code&gt;.then&lt;/code&gt; accepts a callback function as its first argument. The callback's argument is the value passed to the &lt;code&gt;resolve&lt;/code&gt; callback. Once 2 seconds has passed, the &lt;code&gt;.then&lt;/code&gt; function will receive the value and log &lt;code&gt;10&lt;/code&gt; to the console. In the event more operations need to be done we can return a value from &lt;code&gt;.then&lt;/code&gt; and pass it to the next one 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;valueAfter2seconds&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;value&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="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// 10&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&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="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;newValue&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="nx"&gt;newValue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// 15&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;newValue&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;10&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;otherValue&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;otherValue&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="c1"&gt;// 5&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A bit of a contrived example, but hopefully it makes the point.&lt;/p&gt;

&lt;p&gt;You would typically handle any errors within the &lt;code&gt;.catch&lt;/code&gt; method. Since promises are asynchronous, async code is taken out of the original execution context (how code is parsed), the original error cannot be handled in synchronous code. The error will be lost. In the context of node, this would raise an uncaught exception error and cause the server code to crash. This is one of many reasons why handling async errors is important.&lt;/p&gt;

&lt;h2&gt;
  
  
  Alternatives for promise execution
&lt;/h2&gt;

&lt;p&gt;Some alternatives to consider execution order for async code is to use built-in &lt;code&gt;promise&lt;/code&gt; methods like &lt;code&gt;Promise.all&lt;/code&gt;, &lt;code&gt;generator&lt;/code&gt; functions, or using &lt;code&gt;async&lt;/code&gt;/&lt;code&gt;await&lt;/code&gt; which was introduced to javascript in 2017. &lt;/p&gt;

&lt;h3&gt;
  
  
  Normal individual promise handling
&lt;/h3&gt;

&lt;p&gt;Lets assume that we have some tasks to run:&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;task1&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="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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="mi"&gt;1000&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;function&lt;/span&gt; &lt;span class="nf"&gt;task2&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="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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="mi"&gt;500&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;function&lt;/span&gt; &lt;span class="nf"&gt;task3&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="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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;3&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="mi"&gt;2000&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and we want to run those in a specific order where each one logs a value in numerical order. The first thought would be to do something like this:&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;task1&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;value&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;task 1&lt;/span&gt;&lt;span class="dl"&gt;'&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="nf"&gt;task2&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;value&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;task 2&lt;/span&gt;&lt;span class="dl"&gt;'&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="nf"&gt;task3&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;value&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;task 3&lt;/span&gt;&lt;span class="dl"&gt;'&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;// 'task 2' 2&lt;/span&gt;
&lt;span class="c1"&gt;// 'task 1' 1&lt;/span&gt;
&lt;span class="c1"&gt;// 'task 3' 3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The issue above is that the order in which they are resolved may be different based on the time each are completed. Since the time for task 2 is 0.5 seconds it will log first, then task 1, and last is task 3. While this looks somewhat like it should execute in order, because of these times that the promises resolve, they don't. Let's consider this code instead:&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;task1&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;value&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;task 1&lt;/span&gt;&lt;span class="dl"&gt;'&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="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;task2&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;value&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;task 2&lt;/span&gt;&lt;span class="dl"&gt;'&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="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;task3&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;value&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;task 3&lt;/span&gt;&lt;span class="dl"&gt;'&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="p"&gt;})&lt;/span&gt;

&lt;span class="c1"&gt;// "task 1" 1&lt;/span&gt;
&lt;span class="c1"&gt;// "task 2" 2&lt;/span&gt;
&lt;span class="c1"&gt;// "task 3" 3 &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A promise waits to be resolved before passing the resolved value to the &lt;code&gt;.then&lt;/code&gt; method. A promise can, then, be returned from a &lt;code&gt;.then&lt;/code&gt; method and will resolve before being passed down the chain in the next &lt;code&gt;.then&lt;/code&gt; method call. Above we are calling &lt;code&gt;task1()&lt;/code&gt; and chaining a &lt;code&gt;.then&lt;/code&gt;. Once the value is resolved it's passed to the callback where it is logged (&lt;code&gt;"task 1" 1&lt;/code&gt;). We then return the promise &lt;code&gt;task2()&lt;/code&gt; from the first &lt;code&gt;.then&lt;/code&gt;. Once &lt;code&gt;task2()&lt;/code&gt; is resolved, its value is passed to the next call of &lt;code&gt;.then&lt;/code&gt; and the value is logged to the console (&lt;code&gt;"task 2" 2&lt;/code&gt;) and so on.&lt;/p&gt;

&lt;h3&gt;
  
  
  Promise.all
&lt;/h3&gt;

&lt;p&gt;The promise object comes with a method that allows you to return resolved values in order... &lt;code&gt;Promise.all()&lt;/code&gt;. The method takes an array of promises as a function. So we can pass the called functions in an array to the method:&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;allPromises&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;all&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nf"&gt;task1&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nf"&gt;task2&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nf"&gt;task3&lt;/span&gt;&lt;span class="p"&gt;()])&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;allPromises&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;values&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;values&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
  &lt;span class="c1"&gt;// [1,2,3]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When all promises have been resolved, the promise that is returned from &lt;code&gt;allPromises&lt;/code&gt; will be an array of values in the order they were passed in which outputs the order we expect. Even though the order is preserved, &lt;code&gt;task2&lt;/code&gt; will still, technically, resolve before the other two functions. One issue with using this method is that if one of those promises rejects (throws an error) then all promises in the array reject. If you want something where you would like any resolved values and handle the rejected value separately, then &lt;code&gt;Promise.allSettled&lt;/code&gt; should be considered.&lt;/p&gt;

&lt;h3&gt;
  
  
  Using Generators
&lt;/h3&gt;

&lt;p&gt;One alternative to running promises in a specific order without chaining a &lt;code&gt;.then&lt;/code&gt; to everything is to use &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function*" rel="noopener noreferrer"&gt;generator&lt;/a&gt; functions. They follow the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols#the_iterator_protocol" rel="noopener noreferrer"&gt;iterator&lt;/a&gt; protocol by providing a &lt;code&gt;next&lt;/code&gt; method and a &lt;code&gt;done&lt;/code&gt; value that indicates if the iterations are complete. To define a generator function, you use the function keyword followed by an asterisk (*).&lt;/p&gt;

&lt;p&gt;Generators use a keyword &lt;code&gt;yield&lt;/code&gt; that stops execution and yields a value to be returned from the generator. When the last yield expression is reached or a return value is reached, the &lt;code&gt;done&lt;/code&gt; value of the generator is flipped from &lt;code&gt;false&lt;/code&gt; to &lt;code&gt;true&lt;/code&gt; and can no longer be called with the &lt;code&gt;next()&lt;/code&gt; method of the generator. When a &lt;code&gt;yield&lt;/code&gt; keyword is encountered and the value returned from it, the execution of the generator is stopped while preserving the variable bindings for the next execution (basically a fancy way of saying the inner scoped variables aren't reset or lost, but preserved).&lt;/p&gt;

&lt;p&gt;We can start by making a generator function that yield promises:&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="o"&gt;*&lt;/span&gt; &lt;span class="nf"&gt;generator&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;task_1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="nf"&gt;task1&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;task_1&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;task_2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="nf"&gt;task2&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;task_2&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;task_3&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="nf"&gt;task3&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;task_3&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;task_3&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we are defining a generator function named &lt;code&gt;generator&lt;/code&gt; for lack of a more creative word. Each async function is yielded providing a place for execution to stop and return a value. When the generator's next method is called it will yield the next value and continue on that pattern until a return is reached or there is nothing left to yield.&lt;/p&gt;

&lt;p&gt;Now we can create a function that runs the generator and yields all values in the order they were defined in the generator.&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;runGenerator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;genFn&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;gen&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;genFn&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;step&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arg&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;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;gen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arg&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;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;done&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;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&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="nx"&gt;result&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="nf"&gt;then&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;step&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="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;step&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;We will create a &lt;code&gt;runGenerator&lt;/code&gt; function that takes in a generator reference as an argument.  We then store the value to the &lt;code&gt;genFn()&lt;/code&gt; call in a variable called &lt;code&gt;gen&lt;/code&gt; short for generator. Next we create a function called &lt;code&gt;step&lt;/code&gt; inside of the &lt;code&gt;runGenerator&lt;/code&gt; function body. The &lt;code&gt;step&lt;/code&gt; function will take in an argument &lt;code&gt;arg&lt;/code&gt; which will be the resolved value of the yielded promise in the generator.&lt;/p&gt;

&lt;p&gt;We create a base case checking if the &lt;code&gt;result.done&lt;/code&gt; is &lt;code&gt;true&lt;/code&gt;. If it is, the generator is done executing and we can return the value from the final execution of the generator. Otherwise, we resolve a promise with the &lt;code&gt;result.value&lt;/code&gt;. Remember that the value is a promise. Once the promise is resolved, it will pass the resolved value to the &lt;code&gt;.then&lt;/code&gt; method. For clarity, I am passing in a callback to &lt;code&gt;.then&lt;/code&gt; which explicitly calls the &lt;code&gt;step&lt;/code&gt; function with the resolved value to give it back to the generator. You could just pass the reference to &lt;code&gt;.then&lt;/code&gt; ie: &lt;code&gt;.then(step)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We have to pass the resolved value back to the generator so it can pick up execution with the resolved value of the promise. Otherwise it will log undefined. The &lt;code&gt;step&lt;/code&gt; function is executed recursively until the &lt;code&gt;result.done&lt;/code&gt; value is &lt;code&gt;true&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;We then invoke the &lt;code&gt;step&lt;/code&gt; function within the &lt;code&gt;runGenerator&lt;/code&gt; function. Since this function is void, we can just let it log the results.&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;runGenerator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;generator&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;// 1&lt;/span&gt;
&lt;span class="c1"&gt;// 2&lt;/span&gt;
&lt;span class="c1"&gt;// 3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Async and Await
&lt;/h3&gt;

&lt;p&gt;So why learn about generators? You likely don't see them too often. Generators can solve a host of issues with asynchronous javascript. You could use them for pagination, infinite scrolling, or possibly for server code that might require such a thing. Ultimately async and await are kind of an abstraction around generator functions, yet are much cleaner and simpler to implement. Consider this function:&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;actLikeGenerator&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;task_1&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;task1&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;task_1&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;task_2&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;task2&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;task_2&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;task_3&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;task3&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;task_3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="c1"&gt;// 1&lt;/span&gt;
  &lt;span class="c1"&gt;// 2&lt;/span&gt;
  &lt;span class="c1"&gt;// 3&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;According to the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/await#description" rel="noopener noreferrer"&gt;mdn docs&lt;/a&gt;,&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Using await pauses the execution of its surrounding async function until the promise is settled (that is, fulfilled or rejected). When execution resumes, the value of the await expression becomes that of the fulfilled promise.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;What does that mean? When you define an async function with the &lt;code&gt;async&lt;/code&gt; keyword. You can use the &lt;code&gt;await&lt;/code&gt; keyword inside the function body. The &lt;code&gt;await&lt;/code&gt; keyword acts similar to the &lt;code&gt;yield&lt;/code&gt; keyword in a generator function. It will pause the execution of the function until the promise is resolved with a value. Once the promise is resolved, the value is unwrapped (like using a &lt;code&gt;.then&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;So in the example above, when the first &lt;code&gt;await&lt;/code&gt; keyword is encountered, the function pauses execution and waits for &lt;code&gt;task1()&lt;/code&gt; to resolve. Once &lt;code&gt;task1()&lt;/code&gt; resolves, the value is assigned to the variable &lt;code&gt;task_1&lt;/code&gt; and moves to the next line and logs &lt;code&gt;1&lt;/code&gt; to the console. After logging, we move to the next line and encounter another &lt;code&gt;await&lt;/code&gt; keyword. We pause again until &lt;code&gt;task2()&lt;/code&gt; is resolved. We, again, continue execution and assign the resolved value to &lt;code&gt;task_2&lt;/code&gt; and log it to the console (&lt;code&gt;2&lt;/code&gt;) and so on. This provides a much cleaner way of reasoning through asynchronous code.&lt;/p&gt;

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

&lt;p&gt;By understanding how functions are &lt;strong&gt;defined&lt;/strong&gt; will help you better understand how callbacks are defined and used. This isn't just useful for asynchronous javascript, but programming in general. The introduction of promises helped to make asynchronous operations in javascript more manageable, while adding async/await helped to make it more readable. By understanding generators, you can better visualize, roughly, how async/await works under the hood. Let me know your thoughts in the comments!&lt;/p&gt;

</description>
      <category>javascript</category>
    </item>
    <item>
      <title>Adding A Feature to Cypress.JS</title>
      <dc:creator>Raymond </dc:creator>
      <pubDate>Mon, 10 Feb 2025 16:41:13 +0000</pubDate>
      <link>https://dev.to/raymondg/adding-a-feature-to-cypressjs-2o0o</link>
      <guid>https://dev.to/raymondg/adding-a-feature-to-cypressjs-2o0o</guid>
      <description>&lt;h2&gt;
  
  
  Cypress.js
&lt;/h2&gt;

&lt;p&gt;Cypress now has a new feature for automatic browser launch after passing the &lt;code&gt;--browser&lt;/code&gt; flag alone with a good browser name or path! This is a breakdown of the contribution that brought it to life!&lt;/p&gt;

&lt;p&gt;Cypress is a testing framework used to perform end to end (e2e) testing and component testing. It provides a wide range of support for multiple frontend frameworks including Vue, React, and Angular. It has a healthy ecosystem and has over five million downloads a week. Multiple businesses use it in their CI pipeline for test automation.&lt;/p&gt;

&lt;p&gt;The Cypress repo is a package-based mono repo that is handled by &lt;code&gt;Lerna&lt;/code&gt;. &lt;code&gt;Lerna&lt;/code&gt; is powered by &lt;code&gt;nx&lt;/code&gt; under the hood. This allows you to manage workspaces in the root of the repo from the command line and install dependencies that are shared between packages. &lt;code&gt;yarn&lt;/code&gt; is used as the package manager for dependencies.&lt;/p&gt;

&lt;p&gt;Cypress uses Javascript and Typescript as a full stack language. Their frontend components are shared between their &lt;code&gt;launchPad&lt;/code&gt; and another frontend application. The launchpad is used with &lt;code&gt;Electron&lt;/code&gt; which is a tool for creating desktop applications in Javascript. They use node to set up a server and add a series of caching mechanisms utilizing the file system on the host machine for user preferences, projects, etc. Their frontend is in &lt;code&gt;Vue.js&lt;/code&gt; and uses &lt;code&gt;Urql&lt;/code&gt; for their GraphQL client. They utilize a series of tools for GraphQL to create GraphQL object types, queries, mutations, and subscriptions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Data Context
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;data-context&lt;/code&gt; workspace is the core of the application. It is the single source of truth for the data floating around. It uses some Typescript decorators to cache values. It's also used to inject it's &lt;code&gt;this&lt;/code&gt; value in a host of other APIs. It utilizes a &lt;code&gt;singleton&lt;/code&gt; pattern to be consumed by the application. This data context is used as the main GraphQL context for resolvers in the app.&lt;/p&gt;

&lt;h2&gt;
  
  
  The issue
&lt;/h2&gt;

&lt;p&gt;As the application stood, you could pass  &lt;code&gt;--project &amp;lt;project-path&amp;gt;&lt;/code&gt;, &lt;code&gt;--&amp;lt;testing-type&amp;gt;&lt;/code&gt; (component or e2e), and &lt;code&gt;--browser &amp;lt;browser-name-or-path&amp;gt;&lt;/code&gt; flags and have the application automatically launch the browser. The caveat was that you had to pass all of those flags together from the &lt;code&gt;cli&lt;/code&gt; and could not pass the &lt;code&gt;--browser&lt;/code&gt; flag alone. If passing that flag alone, you would reach the view for browser selection. The browser would be highlighted showing the passed browser, but would not automatically launch it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Specs
&lt;/h3&gt;

&lt;p&gt;The use case for the issue was to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;have a browser launch automatically after selection of project and testing type in the application when passing &lt;code&gt;--browser &amp;lt;name-or-path&amp;gt;&lt;/code&gt; alone.&lt;/li&gt;
&lt;li&gt;If name or path was invalid it would render the already created error message without automatically launching the last cached browser.

&lt;ul&gt;
&lt;li&gt;the user would have to dismiss the warning and select the browser from the GUI&lt;/li&gt;
&lt;li&gt;or the user would have to start the process with a good name or path from the &lt;code&gt;cli&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;If the name or path was correct, it would only launch once.&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  Making Some Changes
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ProjectActions.ts
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;data-context&lt;/code&gt; utilizes several different APIs to handle different function calls. These APIs are referred to as &lt;code&gt;actions&lt;/code&gt;. They are class based and provide functionality based on data received from other APIs. The &lt;code&gt;ProjectActions&lt;/code&gt; class is responsible for (given a browser, project, and testing type) launching the browser and given project in its respective test mode.&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;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ProjectActions&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// keep track of launchProject calls&lt;/span&gt;
  &lt;span class="kr"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;globalLaunchCount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
  &lt;span class="nf"&gt;constructor &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kr"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;DataContext&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

  &lt;span class="kr"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;get&lt;/span&gt; &lt;span class="nf"&gt;api &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="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_apis&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;projectApi&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="c1"&gt;// allow the launch count to be read&lt;/span&gt;
  &lt;span class="kd"&gt;get&lt;/span&gt; &lt;span class="nf"&gt;launchCount&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="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;globalLaunchCount&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;launchProject &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;testingType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Cypress&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;TestingType&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;Partial&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;OpenProjectLaunchOpts&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;specPath&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// code omitted for brevity&lt;/span&gt;

    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;launchProject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;browser&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;activeSpec&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="nx"&gt;emptySpec&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;globalLaunchCount&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="c1"&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 main focus here was to have a way to track when &lt;code&gt;launchProject&lt;/code&gt; was called. Since there will be two different scenarios for the browser to launch (i.e. passing 3 flags or passing 1 flag), &lt;code&gt;globalLaunchCount&lt;/code&gt; will be the differentiator. In the event that all 3 flags have been passed by the time we land on the browser selection screen we don't want the function to launch again. So we increment the value after the &lt;code&gt;this.api.launchProject&lt;/code&gt; call just before the return. If this doesn't make sense just yet, that's ok, it will soon.&lt;/p&gt;

&lt;h3&gt;
  
  
  LocalSettings.ts
&lt;/h3&gt;

&lt;p&gt;The GraphQL layer uses a tool called &lt;a href="https://nexusjs.org/" rel="noopener noreferrer"&gt;GraphQL Nexus&lt;/a&gt;. It provides a declarative way to create schemas, among other things, in GraphQL. When you define a type with nexus, it auto-generates type-documents for Typescript type-safety (super nice feature).&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;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;LocalSettingsPreferences&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;objectType&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;LocalSettingsPreferences&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;local setting preferences&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nf"&gt;definition &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="c1"&gt;// ...&lt;/span&gt;
    &lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;shouldLaunchBrowserFromOpenBrowser&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Determine if the browser should launch when the browser flag is passed alone&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;_source&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;_args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ctx&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;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;cliBrowser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;coreData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cliBrowser&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;cliBrowser&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="kc"&gt;false&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;browser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_apis&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;browserApi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ensureAndGetByNameOrPath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cliBrowser&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;shouldLaunch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Boolean&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;browser&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;actions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;project&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;launchCount&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;0&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;shouldLaunch&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;e&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 error is thrown, browser doesn't exist&lt;/span&gt;
          &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;false&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="c1"&gt;// ...&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;Let's cover what's going on here. &lt;code&gt;objectType&lt;/code&gt; is a function coming from &lt;code&gt;nexus&lt;/code&gt;. It allows you to create a GraphQL object type with a &lt;code&gt;name&lt;/code&gt; and a &lt;code&gt;definition&lt;/code&gt; and optionally a &lt;code&gt;description&lt;/code&gt;. The argument to the &lt;code&gt;definition&lt;/code&gt; method is an object (&lt;code&gt;t&lt;/code&gt;) that provides helper methods to define &lt;code&gt;fields&lt;/code&gt;, &lt;code&gt;scalars&lt;/code&gt;, and &lt;code&gt;resolvers&lt;/code&gt;. &lt;code&gt;t.boolean&lt;/code&gt; indicates a boolean scalar. This helper method takes one required argument (a field name) and an optional second argument (an object). Here, &lt;code&gt;shouldLaunchBrowserFromOpenBrowser&lt;/code&gt; (I know, specific) is the field name for the &lt;code&gt;LocalSettingsPreferences&lt;/code&gt; object type and is intended to resolve to a boolean value.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;resolve&lt;/code&gt; method takes in 4 arguments. If you would like to have a quick rundown of them, you can find a quick diagram &lt;a href="https://nexusjs.org/docs/guides/schema#basic-anatomy" rel="noopener noreferrer"&gt;here&lt;/a&gt;. For the sake of this, we are just concerned about the 3rd argument... the &lt;code&gt;context&lt;/code&gt;. This is the &lt;code&gt;data-context&lt;/code&gt; passed in on the server during initialization and becomes available to all resolvers. The &lt;code&gt;cliBrowser&lt;/code&gt; is the browser (name or path) that was passed in the cli. If nothing was passed we can return &lt;code&gt;false&lt;/code&gt; right away indicating we should not launch the browser. If it does exist, the data context provides a nice async function from the browser API, &lt;code&gt;ensureAndGetByNameOrPath&lt;/code&gt;, that can attempt to find the browser on the machine. This helps with two things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Code reuse-ability. No need to reinvent the wheel. You know it exists because this was already baked in before you got here.&lt;/li&gt;
&lt;li&gt; Provides a way to tell if the actual browser (name or path) is valid.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If the &lt;code&gt;browser&lt;/code&gt; does exist, we can convert the value to a boolean and also check that the &lt;code&gt;launchProject&lt;/code&gt; function hasn't been called based on the &lt;code&gt;launchCount&lt;/code&gt; being strictly equal to &lt;code&gt;0&lt;/code&gt; allowing it to resolve to &lt;code&gt;true&lt;/code&gt; other wise it resolves to &lt;code&gt;false&lt;/code&gt;. If the browser doesn't exist, then the function throws an error. We can catch it and return &lt;code&gt;false&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  OpenBrowser.vue
&lt;/h3&gt;

&lt;p&gt;Let's understand some code that was already present.&lt;/p&gt;

&lt;h4&gt;
  
  
  gql
&lt;/h4&gt;

&lt;p&gt;This function is supplied by &lt;code&gt;Urql&lt;/code&gt; to generate &lt;code&gt;DocumentNodes&lt;/code&gt;. Here, this function is creating a document node called &lt;code&gt;OpenBrowser_LaunchProject&lt;/code&gt; which is a &lt;code&gt;mutation&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="nx"&gt;gql&lt;/span&gt;&lt;span class="s2"&gt;`
mutation OpenBrowser_LaunchProject ($testingType: TestingTypeEnum!)  {
  launchOpenProject {
    id
  }
  setProjectPreferencesInGlobalCache(testingType: $testingType) {
    currentProject {
      id
      title
    }
  }
}
`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;$testingType&lt;/code&gt; is an argument to the &lt;code&gt;OpenBrowser_LaunchProject&lt;/code&gt; document node that is an &lt;code&gt;enum&lt;/code&gt;. The mutation to &lt;code&gt;launchOpenProject&lt;/code&gt; corresponds to a server mutation of the same name and is intended to launch the current project with the current testing type. The other mutation is to set the current testing type in a global cache.&lt;/p&gt;

&lt;h4&gt;
  
  
  launchOpenProject
&lt;/h4&gt;

&lt;p&gt;This will be the mutation used to launch the project&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;launchOpenProject&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useMutation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;OpenBrowser_LaunchProjectDocument&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;useMutation&lt;/code&gt; is a hook from &lt;code&gt;Urql&lt;/code&gt; that abstracts away some of the common needs of creating mutations. We pass the &lt;code&gt;OpenBrowser_LaunchProjectDocument&lt;/code&gt; that is imported from generated document nodes based on the &lt;code&gt;gql&lt;/code&gt; definition of &lt;code&gt;OpenBrowser_LaunchProject&lt;/code&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  launching
&lt;/h4&gt;

&lt;p&gt;This is a Vue &lt;code&gt;ref&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;const&lt;/span&gt; &lt;span class="nx"&gt;launching&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;refs&lt;/code&gt; are values to be directly mutated. Unlike React when setting or updating state, the value can be directly updated or &lt;code&gt;mutated&lt;/code&gt; to trigger component updates based on reassignment of the &lt;code&gt;launching&lt;/code&gt; ref's &lt;code&gt;value&lt;/code&gt; property. The &lt;code&gt;value&lt;/code&gt; property is the current value of the ref. In this case it is initialized to &lt;code&gt;false&lt;/code&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  launch
&lt;/h4&gt;

&lt;p&gt;This function was already present. It was used to emit an event called &lt;code&gt;@launch&lt;/code&gt; from a child Vue component form submission to launch the project. The syntax &lt;code&gt;@launch&lt;/code&gt; is a custom event defined as a &lt;code&gt;v-on&lt;/code&gt; handler. You can learn more about events in Vue &lt;a href="https://vuejs.org/guide/components/events.html" rel="noopener noreferrer"&gt;here&lt;/a&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;const&lt;/span&gt; &lt;span class="nx"&gt;launch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;testingType&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&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="nx"&gt;currentProject&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;currentTestingType&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;testingType&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;launching&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="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;launching&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;launchOpenProject&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;executeMutation&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="nx"&gt;testingType&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;

    &lt;span class="nx"&gt;launching&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&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 &lt;code&gt;launch&lt;/code&gt; function finds the current &lt;code&gt;testingType&lt;/code&gt; based on a query. If there is a testing type selected, and the launching ref's value is false, we set the &lt;code&gt;launching.value&lt;/code&gt; to &lt;code&gt;true&lt;/code&gt; which triggers a component update for a loading state for the UI. It executes the &lt;code&gt;launchProject.executeMutation&lt;/code&gt; method of the &lt;code&gt;useMutation&lt;/code&gt; hook created earlier and takes in the required testing type as the argument for the mutation. If that launch occurs or not, the component state needs to be updated to reflect the function has completed and set &lt;code&gt;launching.value&lt;/code&gt; to false. &lt;/p&gt;

&lt;h4&gt;
  
  
  OpenBrowser_LocalSettings
&lt;/h4&gt;

&lt;p&gt;This is a newly created document node&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;gql&lt;/span&gt;&lt;span class="s2"&gt;`
query OpenBrowser_LocalSettings {
  localSettings {
    preferences {
      shouldLaunchBrowserFromOpenBrowser
    }
  }
}
`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This document node's sole responsibility is to grab the value for &lt;code&gt;shouldLaunchBrowserFromOpenBrowser&lt;/code&gt; which will either be &lt;code&gt;true&lt;/code&gt; or &lt;code&gt;false&lt;/code&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  lsQuery
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;lsQuery&lt;/code&gt; uses another hook from &lt;code&gt;Urql&lt;/code&gt;. This was a newly created query. As for the naming, I could have been a little more explicit to state that this was &lt;code&gt;localSettingsQuery&lt;/code&gt; and probably should have done so.&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;lsQuery&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useQuery&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;query&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;OpenBrowser_LocalSettingsDocument&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;requestPolicy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;network-only&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Like the mutation, we pass in a document node for the query. The thing to note here is the &lt;code&gt;requestPolicy&lt;/code&gt; property. During initialization of the app and the &lt;code&gt;Urql&lt;/code&gt; client, there is an in-memory caching policy set up to prevent unnecessary network requests. It provides a quicker lookup for data already received and reduces api calls for commonly used data. When setting the caching policy it applies to &lt;strong&gt;all&lt;/strong&gt; queries that the client performs by default. Since the first run of this function grabbed stale data out of the cache, it would call the launch function again based on the &lt;code&gt;shouldLaunchBrowserFromOpenBrowser&lt;/code&gt; always evaluating to &lt;code&gt;true&lt;/code&gt; from the cache if all the criteria were good for launching initially.&lt;/p&gt;

&lt;p&gt;Fortunately, there is a way to change the caching policy per query. By adding the &lt;code&gt;requestPolicy&lt;/code&gt; with &lt;code&gt;network-only&lt;/code&gt; it will ensure that the value for &lt;code&gt;shouldLaunchBrowserFromOpenBrowser&lt;/code&gt; will be the most up-to-date and, subsequently, only call the function once.&lt;/p&gt;

&lt;h4&gt;
  
  
  launchIfBrowserSetInCli
&lt;/h4&gt;

&lt;p&gt;This newly created function, like the resolver for &lt;code&gt;shouldLaunchBrowserFromOpenBrowser&lt;/code&gt;, reuses functionality.&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;launchIfBrowserSetInCli&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;shouldLaunchBrowser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;lsQuery&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;data&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="nx"&gt;localSettings&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;preferences&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;shouldLaunchBrowserFromOpenBrowser&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;shouldLaunchBrowser&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;launch&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We grab the &lt;code&gt;shouldLaunchBrowserFromOpenBrowser&lt;/code&gt; field. We then check to see if its truthy, or rather that it's true, and launch the browser. Either way, we return. Since the &lt;code&gt;launch&lt;/code&gt; function already triggers component updates and UI updates, there is no need to create that logic.&lt;/p&gt;

&lt;h4&gt;
  
  
  onMounted
&lt;/h4&gt;

&lt;p&gt;This is a lifecycle hook from Vue. The anonymous callback function will be executed when the component is mounted (rendered) to the screen.&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;onMounted&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;launchIfBrowserSetInCli&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;We simply call &lt;code&gt;launchIfBrowserSetInCli&lt;/code&gt; when the component mounts and let the function do what is needs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Putting it all together
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;When a user passes &lt;code&gt;--browser chrome&lt;/code&gt; to the cypress cli (assuming chrome is installed), the user will be prompted to select an existing project. &lt;/li&gt;
&lt;li&gt;Once the user chooses the project, another screen renders to allow the user to select the testing type (e2e or component). &lt;/li&gt;
&lt;li&gt;On the final screen for browser selection during component mount, the &lt;code&gt;lauchIfBrowserSetInCli&lt;/code&gt; function is executed based on the callback to &lt;code&gt;onMounted&lt;/code&gt;. &lt;/li&gt;
&lt;li&gt;A query to the &lt;code&gt;localSettings&lt;/code&gt; object type is executed for the field &lt;code&gt;shouldLaunchBrowserFromOpenBrowser&lt;/code&gt;. 

&lt;ul&gt;
&lt;li&gt;The resolver runs, and finds that the browser was passed to the cli, so it attempts to look it up. &lt;/li&gt;
&lt;li&gt;In this case we are successful and need to check if &lt;code&gt;launchCount&lt;/code&gt; has been called. &lt;/li&gt;
&lt;li&gt;Since &lt;code&gt;--browser&lt;/code&gt; was passed alone &lt;code&gt;launchProject&lt;/code&gt; should not have been called, so the &lt;code&gt;launchCount&lt;/code&gt; should evaluate to 0 and the resolver should return &lt;code&gt;true&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;The query value is received and the &lt;code&gt;if&lt;/code&gt; block is executed inside of &lt;code&gt;launchIfBrowserSetInCli&lt;/code&gt; and the &lt;code&gt;launch&lt;/code&gt; function is called. &lt;/li&gt;
&lt;li&gt;The launch function updates the &lt;code&gt;launching&lt;/code&gt; ref and executes a mutation to &lt;code&gt;launchOpenProject&lt;/code&gt; to open the browser.&lt;/li&gt;
&lt;li&gt;The browser is launched and the &lt;code&gt;launching&lt;/code&gt; ref is flipped to &lt;code&gt;false&lt;/code&gt; to show the updated opened browser state.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Since it is possible that a user can pass all flags and launch directly from the main page view, we can differentiate the calls to &lt;code&gt;launchProject&lt;/code&gt; in &lt;code&gt;ProjectActions&lt;/code&gt;.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The user passes all flags &lt;code&gt;--project ./some/path --e2e --browser chrome&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;We have all the information we need to launch a project, so a mutation is sent to launch the project from the main view.&lt;/li&gt;
&lt;li&gt;Once the mutation is executed, the loading state is stopped and we are brought to the browser selection screen.&lt;/li&gt;
&lt;li&gt;Since the &lt;code&gt;launchProject&lt;/code&gt; method has been called, &lt;code&gt;launchCount&lt;/code&gt; has been incremented evaluating to 1. The query for &lt;code&gt;shouldLaunchBrowserFromOpenBrowser&lt;/code&gt; returns false, skipping the &lt;code&gt;if&lt;/code&gt; block in &lt;code&gt;launchIfBrowserSetInCli&lt;/code&gt; and returning.&lt;/li&gt;
&lt;li&gt;The UI for an already opened browser is shown.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Lets assume that a user passes only the browser flag but it is incorrect.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;User passes &lt;code&gt;--browser doesntExist&lt;/code&gt; to the cli.&lt;/li&gt;
&lt;li&gt;After going through project and testing type selection the &lt;code&gt;launchIfBrowserSetInCli&lt;/code&gt; function is called.&lt;/li&gt;
&lt;li&gt;A query is made to the browser.&lt;/li&gt;
&lt;li&gt;A "browser" was passed to the cli so we can move on and pass it to &lt;code&gt;ensureAndGetByNameOrPath&lt;/code&gt; in the resolver. &lt;/li&gt;
&lt;li&gt;Since the browser doesn't exist, an error is throw from &lt;code&gt;ensureAndGetByNameOrPath&lt;/code&gt; and we return false.&lt;/li&gt;
&lt;li&gt;The browser is not launched and a dismissible error is presented to the user letting them know that the browser wasn't found on the system.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;During testing of this flow, I found that the &lt;code&gt;launchProject&lt;/code&gt; method was being called when it shouldn't have been when reaching the browser selection screen in some instances. I inadvertently stumbled across a silent bug. There was a variable &lt;code&gt;wasBrowserSetInCli&lt;/code&gt; which was a boolean that indicated if something was passed as a browser to the cli specifically. It did not perform checks on if it was a valid browser. So it would attempt to launch and fail. After some banging around and getting some much needed help from a maintainer, the issue was narrowed down to that variable. Swapping it out for the more precise &lt;code&gt;shouldLaunchBrowserFromOpenBrowser&lt;/code&gt; field solved the issue.&lt;/p&gt;

&lt;h2&gt;
  
  
  Recap
&lt;/h2&gt;

&lt;p&gt;Now users can pass a &lt;code&gt;--browser&lt;/code&gt; flag alone with a name or path and  select project and testing type options in the application before the browser is automatically launched. This helps to improve UX/DX by allowing a user to set up a script to run in a default browser and to be able to select between multiple projects and testing types in their local environment. This request has been ongoing since &lt;code&gt;v10&lt;/code&gt; and is now available in &lt;code&gt;v13.4.0&lt;/code&gt; and up!&lt;/p&gt;

&lt;p&gt;This was a challenging PR to make. I ended up learning a lot. Before making this contribution, I knew nothing about GraphQL and the tooling around it. I knew of Typescript, but ended up taking a deeper dive since it was needed to navigate the codebase. I learned a little about Vue and the things I could and couldn't do. I was able to keep some code DRY as well. This was a pretty large and extensive code base and ended up reading a lot of it to fit the pieces together. In the end, this was a great opportunity to play with production code, give back to the development community, and to push the limits of what I know to add to the tool belt. &lt;/p&gt;

&lt;p&gt;Thank you to the maintainers for their reviews and help along the way!&lt;/p&gt;

</description>
      <category>graphql</category>
      <category>testing</category>
      <category>typescript</category>
      <category>vue</category>
    </item>
  </channel>
</rss>
