<?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: Chris Andrade</title>
    <description>The latest articles on DEV Community by Chris Andrade (@chrisjandrade).</description>
    <link>https://dev.to/chrisjandrade</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%2F829405%2F7cefb7d7-74fb-4f52-8f0d-5be7447668c5.jpeg</url>
      <title>DEV Community: Chris Andrade</title>
      <link>https://dev.to/chrisjandrade</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/chrisjandrade"/>
    <language>en</language>
    <item>
      <title>Asynchronous Programming with JavaScript/TypeScript</title>
      <dc:creator>Chris Andrade</dc:creator>
      <pubDate>Tue, 09 May 2023 00:27:13 +0000</pubDate>
      <link>https://dev.to/chrisjandrade/asynchronous-programming-with-javascripttypescript-3g9o</link>
      <guid>https://dev.to/chrisjandrade/asynchronous-programming-with-javascripttypescript-3g9o</guid>
      <description>&lt;h2&gt;
  
  
  Before Promises there were callbacks
&lt;/h2&gt;

&lt;p&gt;Event handling before promises were introduced were done via callbacks.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Before libraries and fetch there was XMLHttpRequest&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Early JavaScript involved usage of call back functions.  In the example below the developer needs to write an onreadystatechange function to handle when an asyncronous request was completed.  The structure below is similar analogous to the way we write event listeners for DOM elements.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var xhttp = new XMLHttpRequest();
// create a callback function which will be fulfilled when the request completes

xhttp.onreadystatechange = function() {
    if (this.readyState == 4 &amp;amp;&amp;amp; this.status == 200) {
       // Typical action to be performed when the document is ready:
       document.getElementById("demo").innerHTML = xhttp.responseText;
    }
};
xhttp.open("GET", "filename", true);
xhttp.send();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Abstracting away the XMLHttpRequest&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Various libraries created their owns mechanisms to make code like the above easier.  For example ExtJS, see &lt;a href="https://www.extjs-tutorial.com/extjs/ajax-request-in-extjs4"&gt;https://www.extjs-tutorial.com/extjs/ajax-request-in-extjs4&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;        Ext.Ajax.request({
            url: '/api/students',
            method: 'GET',
            timeout: 60000,
            params:
            {
                id: 1 // loads student whose Id is 1
            },
            headers:
            {
                'Content-Type': 'application/json'
            },
            success: function (response) {

            },
            failure: function (response) {
                Ext.Msg.alert('Status', 'Request Failed.');

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Writing our own XMLHttpRequest Library&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We begin to see some improved code re-use and abstraction.&lt;/p&gt;

&lt;p&gt;Can we make our own call-back style library to make XML Http Requests? Sure Why Not?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
var Request = {

  get: function (url, success, failure) {
     var xhr = new XMLHttpRequest();

     xhr.onreadystatechange = function () {
       // 4 means we're done see https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/readyState
       if (this.readyState === 4) {
        if (this.statusCode &amp;gt;= 200 &amp;amp;&amp;amp; this.statusCode &amp;lt; 300) {
           success(xhr.responseText);
        } else {
          failure(xhr.responesText);
        }
       }
     };
  };

  Request.get('/services/something',
    function (response) {
      console.log(response);
    },
    function (err) {
      console.error(err);
    }
};

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Callback Hell&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;There some potential issues. When we start having to chain calls together, it gets messy.  The example below uses jQuery to write functions to call various REST api.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
function getUser(success, failure) {
  $.get('services/user', function (response) {
    try {
      success(JSON.parse(response));
    } catch (err) {
      failure(response);
    }
  });
}

function getPermissions(userId, success, failure) {
  $.get('services/permissions/' + userId, function (response) {
    try {
      success(JSON.parse(response));
    } catch (err) {
      failure(err);
    }
  });
}

function getCurrentTime(success, failure) {
  $.get('services/currentTime', function (response) {
    try {
      success(JSON.parse(response));
    } catch (err) {
      failure(err);
    }
  });
}

// lets get the user
// check if they have permission
// if they do then get the time

function getTimeForUser(callback) {

  getUser(
    function (user) {
      getPermissions(user.userId,
        function (permissions) {
          if (permissions.canDoThing) {
            getCurrentTime(
              function (currentTime) {
                callback(null, currentTime);
              },
              function (error) {
                callback(error, null);
              }
            );
          }
        },
        function (error) {
          console.error('Failed to get permissions);
          callback(error, null);
        })
    },
    function (user) {
      console.error('Couldn\'t get the user');
      callback(error, null);
    });
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;&lt;em&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise"&gt;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The Promise object represents the eventual completion (or failure) of an asynchronous operation and its resulting value.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It's easy to see the challenge of maintaining asynchronous codes using only callbacks.  Promises provide a new mechanism for transfering/representing asynchronous state.  Yes there are callbacks, but they are abstracted away in a variable we can use later.&lt;/p&gt;

&lt;h3&gt;
  
  
  Basic structure
&lt;/h3&gt;

&lt;p&gt;The basic structure of a promise is &lt;code&gt;then&lt;/code&gt; and &lt;code&gt;catch&lt;/code&gt;.  See example below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function getThing() {
  return new Promise((resolve, reject) =&amp;gt; {
    setTimeout(() =&amp;gt; {
      resolve('thing');
    }, 1000);
  });
}

const prom = getThing();

prom.then(
  // success handler
  function (thing) {
    console.log('I got the thing');
  },
  // second argument is failure, using this is considered an anti-pattern
  // see anti-patterns section for promises
  function (error) {
    console.error('I failed');
  }
// we can catch errors like this too
).catch((error) =&amp;gt; {
  console.error('I failed');
})

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  Promises make things cleaner ( a bit)
&lt;/h3&gt;

&lt;p&gt;Promises return an object which represents a value to be eventually fulfilled.  It allows us to chain multiple asyncronous parts of code together more cleanly.  Promise chains follow the basic structure of &lt;code&gt;then&lt;/code&gt;, &lt;code&gt;then&lt;/code&gt;, &lt;code&gt;catch&lt;/code&gt; &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Basic Promise Chain Structure&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Chaining promises together allows us to more cleanly&lt;br&gt;
write a sequence of asyncronous actions.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// then
Promise.resolve().then(
  // then
  () =&amp;gt; Promise.resolve()).then(
  // catch
  () =&amp;gt; Promise.reject('error')).catch(
      (err) =&amp;gt; console.error('An error occured =&amp;gt;', err));
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;A more useful promise chain example&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The code below represents requests to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Get a User&lt;/li&gt;
&lt;li&gt;Get Permissions for a user&lt;/li&gt;
&lt;li&gt;Get the Current Time&lt;/li&gt;
&lt;li&gt;Composing the above 3 functions together to make another function.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function getUser() {
  return fetch('services/user').
    then((response) =&amp;gt; response.json());
}

function getPermissions(userId) {
  return fetch('services/permissions/' + userId).
    then((response) =&amp;gt; response.json());
}

function getCurrentTime() {
  return fetch('services/currentTime').
    then((response) =&amp;gt; response.json());
}

function getTimeForUser() {
  // get the user
  getUser().then(
    // get the permissions
    (user) =&amp;gt; 
  // get permissions
  getPermissions(user.userId)).then(
      (permissions) =&amp;gt; {
        if (permissions.canDoThing) {
          return true;
        } else {
          return false
        }
      }).then(
  // if they have permission
  (hasPermission) =&amp;gt; {
    if (hasPermission) {
      return getCurrentTime();
    } else {
      return Promise.reject('doesn\'t have permission');
    }
  // catch - all
  }).catch((err) =&amp;gt; {
        console.error('Failed to get time');
        return Promise.reject(err);
      });
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Promise Anti-Patterns
&lt;/h3&gt;

&lt;p&gt;Although Promises clearly have the ability to improve things here are a few mistakes that are commonly made.&lt;br&gt;
&lt;em&gt;see &lt;a href="https://github.com/petkaantonov/bluebird/wiki/Promise-anti-patterns#the-deferred-anti-pattern"&gt;https://github.com/petkaantonov/bluebird/wiki/Promise-anti-patterns#the-deferred-anti-pattern&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Deferred anti-pattern&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is when you are creating promises for no reason when you already have 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;function getThingsDeferredAntiPattern() {
  return new Promise((resolve, reject) =&amp;gt; {
    fetch('/services/thing').then(
      (thing) =&amp;gt; resolve(thing)).
      catch((err) =&amp;gt; reject(err));
  });
}

function getThings() {
  return fetch('/services/thing');
}

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Nesting Promises&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is often the fallback of developers who had previously worked with callbacks.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/**
 * NO
 */
getCurrentTimeForUserNested() {
  return getUser().then(
    (user) =&amp;gt; {
      getPermissions(user.userId).then(
        (permissions) =&amp;gt; {
          if (permissions.canDoThing) {
            return getCurrentTime();
          }
        })
    });
}

/**
 * Using promises properly, remember that a promise is an object
 * so we can chain then more neatly
 */
getCurrentTimeForUser() {
  return getUser().then(
    (user) =&amp;gt; this.getPermissions(user.userId)).then(

    (permissions) =&amp;gt; permissions.canDoThing).then(

    (canDoThing) =&amp;gt; {
      if (canDoThing) {
        return getCurrentTime();
      } else {
        return Promise.reject(new Error('User doesn't have permission'));
      }
    });
}

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;The .then(success, fail) anti-pattern&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It's considered bad practice to use the second argument of a &lt;code&gt;then&lt;/code&gt; statement.  Using these tend to devolve into callback chains.&lt;/p&gt;

&lt;p&gt;Using the above example belowL&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;getCurrentTimeForUser() {
  return getUser().then(
    (user) =&amp;gt; {
      return getPermissions(user.userId).then(
        (permissions) =&amp;gt; {
          if (permissions.canDoThing) {
            return this.getCurrentTime();
          } else {
            return Promise.reject('User doesn\'t have permission');
          }
        },
        (error) =&amp;gt; Promise.reject('Couldn\'t get permissions =&amp;gt;', error));
    },
    (error) =&amp;gt; Promise.reject('Couldn\'t get user'));
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Async-Await Syntactic Sugar
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;The async and await keywords enable asynchronous, promise-based behavior to be written in a cleaner style, avoiding the need to explicitly configure promise chains.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;em&gt;see &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function"&gt;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Even though the readability is greatly improved it still doesn't read as smoothly as ordinary code. Async-Await was introduced as syntactic sugar that improves the readability of promises.&lt;/p&gt;

&lt;p&gt;The example below expands on the getCurrentTimeForUser method and writes it in a cleaner way.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Revisiting our Promise example&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function getUser() {
  return fetch('services/user').
    then((response) =&amp;gt; response.json());
}

function getPermissions(userId) {
  return fetch('services/permissions/' + userId).
    then((response) =&amp;gt; response.json());
}

function getCurrentTime() {
  return fetch('services/currentTime').
    then((response) =&amp;gt; response.json());
}

// lets re-write this using promises
async function getTimeForUser() {
  try {
    const user = await getUser();
    const permissions = await getPermissions(user.userId);

    if (permissions.canDoThing) {
      const time = await getCurrentTime();
      return time;
    } else {
      return Promise.reject(new Error('Don\'t have permission to do thing'));
    }
  } catch (err) {
    console.error('Failed to get the time for the user');
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Which to use? It depends
&lt;/h3&gt;

&lt;p&gt;There are advantages and disadvantages of using the &lt;code&gt;Promise&lt;/code&gt; style or the &lt;code&gt;Async-Await&lt;/code&gt; style.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Comparing Promises and Async-Await&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function getRandomNumber() {
  return fetch('/services/random').
    then(response =&amp;gt; response.json());
}
// sometimes using async-await is more wordy
function getRandomNumberAlt() {
  const response = await fetch('/services/random');

  return response.json();
}

/**
 * Get numbers using promise style
 */
function getNumbersPromise() {

  const nums = [];
  for (let i = 0, end = 10; i &amp;lt; end; i++) {
    getRandomNumber().then((num) =&amp;gt; {
      // to ensure proper ordering we
      // use closure
      // i think this should work?
      nums[i] = num;
    });
  }

}

/**
 * Get numbers using async-await
 * Using async await can result in more readable code
 */
function getNumbersAsync() {
  const nums = [];

  for (let i = 0, end = 10; i &amp;lt; end; i++) {
    // better this is more obvious
    // since we will wait to get the random
    // number before pushing it into the array
    const num = await getRandomNumber();
    nums.push(num);
  }
}

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  A Brief overview RxJS Observables
&lt;/h2&gt;

&lt;p&gt;Observables are the next iteration of Async Programming in JavaScript/TypeScript.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A representation of any set of values over any amount of time.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;em&gt;see &lt;a href="https://rxjs.dev/api/index/class/Observable"&gt;https://rxjs.dev/api/index/class/Observable&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Promises vs. Observables
&lt;/h3&gt;

&lt;p&gt;A key distinction between &lt;code&gt;Promises&lt;/code&gt; and &lt;code&gt;Observables&lt;/code&gt; is that Observables can represent &lt;em&gt;0&lt;/em&gt;, &lt;em&gt;1&lt;/em&gt; or &lt;em&gt;more&lt;/em&gt; emitted values.  This is similar to an event that can occur many times or not at all, like when the user clicks a button.&lt;/p&gt;

&lt;h3&gt;
  
  
  Observables are Lazy
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Observables are lazy Push collections of multiple values.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;em&gt;see &lt;a href="https://rxjs.dev/guide/observable"&gt;https://rxjs.dev/guide/observable&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What does it practically mean to be lazy?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Why is it that nothing is executed when I call an observable function?  Newcomers to Observables often are confused by the &lt;em&gt;lazy&lt;/em&gt; behavior of Observables.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// a normal http request in angular (or whatever)
getThing(): any {
  return http.get('services/thing');
}

load(): void {
  // this will not invoke an ajax request
  // because we have not subscribed
  service.getThing();
}

loadWorking(): void {
  // this will invoke an ajax request
  // because we have subscribed for changes
  service.getThing().subscribe((data: any) =&amp;gt; {
    this.doSomething(data);
  }
}

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  Observables are like an event, and occur 0 or more times.
&lt;/h3&gt;

&lt;p&gt;Observables are distinct from Promises in their ability to emit multiple values.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Given the following observable&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const observable: Observable&amp;lt;any&amp;gt; = new Observable((subscriber: Subscriber) =&amp;gt; {
  subscriber.next(0);
  subscriber.next(1);
  subscriber.next(2);
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Get only the first value&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I only care about the very first value emitted by an observable.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;observable.pipe(first()).subscribe((value: any) =&amp;gt; {
  console.log({ first: value });
});
// outputs 0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Get only the last value&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I only care about the most recent value emitted by an observable.  &lt;em&gt;last&lt;/em&gt; May be a misnomer since it refers to:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;the last item from the source Observable that satisfies the predicate.&lt;br&gt;
&lt;em&gt;see &lt;a href="https://rxjs.dev/api/operators/last"&gt;https://rxjs.dev/api/operators/last&lt;/a&gt;&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/**
 * I just want the last value emitted
 */
 observable.pipe(last()).subscribe((value: any) =&amp;gt; {
  console.log({ last: value });
 });
 // outputs 2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;A note about toPromise&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The toPromise method returns the value of a completed observable.  This can confusing to some users who expect an observable to emit a value but it does not.&lt;/p&gt;

&lt;p&gt;The code below will never execute the console.log statement because the observable never &lt;em&gt;completed&lt;/em&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;observable.toPromise().then((value: any) =&amp;gt; {
  console.log({ prom: value });
});
// never outputs because toPromise only sends value when an observable is complete
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;toPromise()&lt;/em&gt; will only resolve when an observable value has &lt;em&gt;completed&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cosnt completed: Observable&amp;lt;any&amp;gt; = new Observable((subscriber: Subscriber) =&amp;gt; {
  subscriber.next(0);
  subscriber.next(1);
  subscriber.next(2);
  subscriber.complete();
});

completed.toPromise().then((value: any) =&amp;gt; {
  console.log({ completed: value });
});
// outputs 2

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  Mapping Operators
&lt;/h3&gt;

&lt;p&gt;The various mapping operators allow a you to transform emitted values in an observable.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;map&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The base map operator allows you to transform an emitted value.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--GL9qaV3q--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r4l6s7vs3qerjknaprpo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--GL9qaV3q--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r4l6s7vs3qerjknaprpo.png" alt="Image description" width="612" height="462"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
getCurrentUser(): Observable&amp;lt;any&amp;gt; {
  return http.get('/services/currentUser');
}

// take the observable returned by getCurrentUser
getCurrentUserId(): Observable&amp;lt;string&amp;gt; {
  return getUser().pipe(
    // use map operator to map the user into some other value
    map((user: any) =&amp;gt; user.userId));
}

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;mergeMap/flatMap&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The &lt;em&gt;flatMap&lt;/em&gt; or &lt;em&gt;mergeMap&lt;/em&gt; operator is similar to the base &lt;code&gt;map&lt;/code&gt; operator.  It takes a source observable's emitted values, and then merges them with another observable value to produce a resultant observable value.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--mc9kvqeG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cftny098cmo2j4bidxzi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--mc9kvqeG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cftny098cmo2j4bidxzi.png" alt="Image description" width="800" height="416"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
getPermissions(userId: string): Observable&amp;lt;Permissions&amp;gt; {
  return http.get(`/services/permissions/{$userId}`);
}

getCurrentUserPermissions(user: any): Observable&amp;lt;any&amp;gt; {
  // get the user observable
  const user: Observable&amp;lt;any&amp;gt; = getCurrentUser();

  return user.pipe(
    // use flatmap to combine results of the getPermissions()
    // observable and user observable
    flatMap((user: any) =&amp;gt; getPermissions(user.userId)));
}

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

&lt;/div&gt;



&lt;p&gt;The key takeaway is that when you want to use another observable value, when mapping use the &lt;code&gt;flatMap&lt;/code&gt; or &lt;code&gt;mergeMap&lt;/code&gt; operator.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;concatMap&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;concatMap&lt;/em&gt; allows you to take a collection of values and emit them as distinct values.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--XHVK6Lyw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/obzbi6qowm7idprc9g2c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--XHVK6Lyw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/obzbi6qowm7idprc9g2c.png" alt="Image description" width="800" height="297"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// ids =&amp;gt; [1, 2, 3]
getUsers(ids: string[]): Observable&amp;lt;User[]&amp;gt; {
  return from(ids).pipe(
    // takes the list of ids and make multiple user calls
    concatMap((userId: string) =&amp;gt; getUser(userId)))),
    // convert it to an array of users, we'll explain this later
    reduce((acc: User[], user: User) =&amp;gt; acc.push(user), []);
}

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;reduce&lt;/strong&gt;&lt;br&gt;
&lt;em&gt;reduce&lt;/em&gt; is similar to the javascript &lt;code&gt;Array.reduce&lt;/code&gt; method.  It consists of an accumlated value, and iterated value.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--KjH2z7rW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/y78ox3amg8ks6pb1uvfa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KjH2z7rW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/y78ox3amg8ks6pb1uvfa.png" alt="Image description" width="800" height="264"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;getUsers(ids: string[]): Observable&amp;lt;User[]&amp;gt; {
  return from(ids).pipe(
    // takes the list of ids and make multiple user calls
    concatMap((userId: string) =&amp;gt; http.get(`services/user/${userId}`))),
    // convert it to an array of users, we'll explain this later
    reduce(
      // our accumulator function
      (acc: User[], user: User) =&amp;gt; {
        acc.push(user);
        return acc;
      }, 
      // our starting value
      []);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are many more mapping and other operators, we've only just touched a few of them.&lt;/p&gt;

&lt;h3&gt;
  
  
  Functional Programming with observables
&lt;/h3&gt;

&lt;p&gt;Using observable allows us to compose our observables from other observables&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function getUser(): Observable&amp;lt;any&amp;gt; {
  return http.get('services/user');
}

function getPermissions(userId): Observable&amp;lt;any&amp;gt; {
  return http.get('services/permissions/' + userId);
}

function getCurrentTime(): Observable&amp;lt;number&amp;gt; {
  return http.get('services/currentTime');
}

getTimeForUser(): Observable&amp;lt;number&amp;gt; {
  return getUser().pipe(
    // after we get the user return the user id
    map((user: any) =&amp;gt; user.userId),

    // pass the user id to another observable
    flatMap((userId: string) =&amp;gt; getPermissions(userId)),

    // conditionally continue
    filter((permissions: any) =&amp;gt; permissions.canDoThing),

    // get the current time
    flatMap(() =&amp;gt; getCurrentTime()));
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;see &lt;a href="https://rxjs.dev/guide/operators"&gt;https://rxjs.dev/guide/operators&lt;/a&gt; for a complete list of operators&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Composing Software: An Exploration of Functional Programming and Object Composition in JavaScript by Eric Elliot is a comprehensive overview of functional techniques&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Observable Anti-Patterns
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Nested Subscriptions&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;getTimeForUser(): any {
  // whats wrong here?
  return getUser().subscribe((user: any) =&amp;gt; {
    getPermissions().subscribe((permissions: any) =&amp;gt; {
      if (permissions.canDoThing) {
        return getCurrentTime();
      }
    })
  });
}

// what if any of these observables emit multiple values, or never complete?

// do you see the memory leak? 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Converting to Promise&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// NO!
function getUserPromise(): Promise&amp;lt;any&amp;gt; {
  return new Promise((resolve) =&amp;gt; {
    // do you see the memory leak?
    getUser().subscribe((user) =&amp;gt; {
      resolve(user);
    });
  });
}

// Use built-in functions
function getUserPromiseWorking(): Promise&amp;lt;any&amp;gt; {
  // see caveat about using toPromise above
  return getUser().toPromise();
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Converting from Promise to Observable&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/**
 * Use the from operator to convert from promise to observable
 */
function fromUserPromise(): Observable&amp;lt;any&amp;gt; {
  return from(getUserPromise());
}

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

&lt;/div&gt;



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

&lt;p&gt;Modern JavaScript and TypeScript provide powerful tools for asyncronous programming.  Promises and Async-Await are built in mechanisms that originated from the community and were so widely adopted they were introduced into the ECMA standards.  RxJS Observables are a powerful tool that build on Promises and Async-Await and extend them to create some useful mechanisms that are functionally oriented.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>typescript</category>
      <category>rxjs</category>
    </item>
    <item>
      <title>Fun with JavaScript Arrays</title>
      <dc:creator>Chris Andrade</dc:creator>
      <pubDate>Sat, 12 Mar 2022 02:57:10 +0000</pubDate>
      <link>https://dev.to/chrisjandrade/using-javascript-arrays-effectively-4jjn</link>
      <guid>https://dev.to/chrisjandrade/using-javascript-arrays-effectively-4jjn</guid>
      <description>&lt;p&gt;I don’t often see other developers on my team exploiting the abilities of Arrays in JavaScript.  Here are some fun tricks I often use.&lt;/p&gt;

&lt;h2&gt;
  
  
  Better Conditionals
&lt;/h2&gt;

&lt;p&gt;Its pretty common that I end up needing to write some code to quickly check if some condition is satisfied.&lt;/p&gt;

&lt;h3&gt;
  
  
  Using Arrays for better re-use and readability.
&lt;/h3&gt;

&lt;p&gt;Often times I’ll see code to check for some condition written in the style below.&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;// standard way with chained OR&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;isSupported&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="err"&gt;‘&lt;/span&gt;&lt;span class="nx"&gt;heavy&lt;/span&gt;&lt;span class="err"&gt;’&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt;
    &lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="err"&gt;‘&lt;/span&gt;&lt;span class="nx"&gt;light&lt;/span&gt;&lt;span class="err"&gt;’&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt;
    &lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="err"&gt;‘&lt;/span&gt;&lt;span class="nx"&gt;thick&lt;/span&gt;&lt;span class="err"&gt;’&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt;
    &lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="err"&gt;‘&lt;/span&gt;&lt;span class="nx"&gt;rich&lt;/span&gt;&lt;span class="err"&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;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// this can be reused for other purposes&lt;/span&gt;
&lt;span class="c1"&gt;// also easily editable and understandable&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;supportedTypes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="err"&gt;‘&lt;/span&gt;&lt;span class="nx"&gt;heavy&lt;/span&gt;&lt;span class="err"&gt;’&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="err"&gt;‘&lt;/span&gt;&lt;span class="nx"&gt;light&lt;/span&gt;&lt;span class="err"&gt;’&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="err"&gt;‘&lt;/span&gt;&lt;span class="nx"&gt;thick&lt;/span&gt;&lt;span class="err"&gt;’&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="err"&gt;‘&lt;/span&gt;&lt;span class="nx"&gt;rich&lt;/span&gt;&lt;span class="err"&gt;’&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="c1"&gt;// rather than hard coding an if statement &lt;/span&gt;
&lt;span class="c1"&gt;// or chaining else, we use a list.&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;isSupportedType&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;supportedTypes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;type&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;h3&gt;
  
  
  Using a list to make sure conditions pass
&lt;/h3&gt;

&lt;p&gt;In the example below we can use JavaScripts reduce function to test some variable.&lt;/p&gt;

&lt;p&gt;This example makes sure all conditions pass, but can be easily updated to test for at least one condition passing.&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;// we can define all the criteria we want to pass&lt;/span&gt;
&lt;span class="c1"&gt;// as an array of functions which return true or false &lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;conditions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;number&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;number&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;2&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="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;num&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// use the reduce function to iterate&lt;/span&gt;
  &lt;span class="c1"&gt;// through the conditions we want to test&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;conditions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;pass&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;conditionFn&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class="nx"&gt;pass&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;conditionFn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;num&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Rest Parameters
&lt;/h2&gt;

&lt;p&gt;Somewhat related, it’s sometimes nice to create a function that can deal with an arbitrary amount of arguments.&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;// use the rest operator to collect &lt;/span&gt;
&lt;span class="c1"&gt;// all parameters to an Array&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;logItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;…&lt;/span&gt;&lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&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="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;logItem&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="c1"&gt;// like most people expect&lt;/span&gt;
&lt;span class="nx"&gt;logItem&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;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// or call with arbitrary num of arguments &lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;items&lt;/span&gt; &lt;span class="o"&gt;=&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;2&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="nx"&gt;logItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;…&lt;/span&gt;&lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// or even use an array with the spread operator&lt;/span&gt;

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

&lt;/div&gt;



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