<?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: Guilherme Araujo</title>
    <description>The latest articles on DEV Community by Guilherme Araujo (@guilhermesaraujo).</description>
    <link>https://dev.to/guilhermesaraujo</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%2F2143656%2Fc4199492-32c9-429f-adb7-9074bc41cd9c.jpeg</url>
      <title>DEV Community: Guilherme Araujo</title>
      <link>https://dev.to/guilhermesaraujo</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/guilhermesaraujo"/>
    <language>en</language>
    <item>
      <title>Understanding Lighthouse: The Metrics That Actually Matter for Performance and SEO</title>
      <dc:creator>Guilherme Araujo</dc:creator>
      <pubDate>Thu, 10 Jul 2025 12:52:43 +0000</pubDate>
      <link>https://dev.to/quave/understanding-lighthouse-the-metrics-that-actually-matter-for-performance-and-seo-3h2f</link>
      <guid>https://dev.to/quave/understanding-lighthouse-the-metrics-that-actually-matter-for-performance-and-seo-3h2f</guid>
      <description>&lt;h2&gt;
  
  
  🔍 What Is Lighthouse?
&lt;/h2&gt;

&lt;p&gt;Lighthouse is an automated tool that audits web pages and generates a report about five main categories:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Performance;&lt;/li&gt;
&lt;li&gt;Accessibility;&lt;/li&gt;
&lt;li&gt;Best Practices;
&lt;/li&gt;
&lt;li&gt;SEO;&lt;/li&gt;
&lt;li&gt;Progressive Web App (PWA).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For example, here's the Lighthouse report for dev.to's main page:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn3y9lunr88te68b4onn7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn3y9lunr88te68b4onn7.png" alt="Lighthouse report for dev.to's main page" width="479" height="190"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The report gives each category a score, along with helpful suggestions for improvement. Here, we’ll focus mainly on the &lt;strong&gt;Performance&lt;/strong&gt; category — the one that impacts users the most, and is often the most important when it comes to SEO and UX.&lt;/p&gt;


&lt;h2&gt;
  
  
  Performance
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;Performance&lt;/strong&gt; score in Lighthouse is based on a set of real-world metrics, many of which are part of Google’s &lt;strong&gt;Core Web Vitals&lt;/strong&gt;. These metrics measure how your site loads and responds from the user’s point of view.&lt;/p&gt;

&lt;p&gt;Let’s break them down:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd5ik332bja6psfz54as0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd5ik332bja6psfz54as0.png" alt="Lighthouse report for dev.to's main page" width="634" height="328"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;First Contentful Paint (FCP)&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Measures how long it takes for the first piece of content to show up on the screen, like text or an image. It gives users feedback that something is happening.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Largest Contentful Paint (LCP)&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Tells you how long it takes for the main piece of content to load, usually a large image or headline. It shows when the page becomes useful.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Speed Index&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Tracks how quickly visible parts of the page appear during loading. Lower scores mean faster and smoother loading.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Time to Interactive (TTI)&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Measures how long the page takes to become fully usable. In summary, when a user can click or type without delays.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Total Blocking Time (TBT)&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Adds up how much time the browser is “too busy” to respond to user input, often due to heavy JavaScript tasks.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cumulative Layout Shift (CLS)&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Tracks unexpected layout changes, like when content moves while the page is still loading. This helps prevent those annoying jumps that make users click the wrong thing.&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  How Are Lighthouse Scores Calculated?
&lt;/h2&gt;

&lt;p&gt;Not all metrics count the same toward the final performance score. Metrics like &lt;strong&gt;LCP&lt;/strong&gt; and &lt;strong&gt;TBT&lt;/strong&gt; have more weight because they directly affect how smooth the site feels to real users.&lt;/p&gt;

&lt;p&gt;Lighthouse uses real-world data from tools like the HTTP Archive and Chrome UX Report to compare your site with others on the web.&lt;/p&gt;

&lt;p&gt;Here’s the current weight breakdown:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Largest Contentful Paint (LCP):&lt;/strong&gt; 25%
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Total Blocking Time (TBT):&lt;/strong&gt; 30%
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cumulative Layout Shift (CLS):&lt;/strong&gt; 15%
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;First Contentful Paint (FCP):&lt;/strong&gt; 10%
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Speed Index:&lt;/strong&gt; 10%
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Time to Interactive (TTI):&lt;/strong&gt; 10%&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  What About the Other Categories?
&lt;/h2&gt;

&lt;p&gt;Performance is super important, but the other Lighthouse categories also matter:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Accessibility&lt;/strong&gt; checks if your site works well for people with disabilities.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Best Practices&lt;/strong&gt; makes sure you’re following web and security standards.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;SEO&lt;/strong&gt; looks at basic on-page SEO, like titles, meta tags, and headings.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;PWA&lt;/strong&gt; checks if your site can work like an app on mobile devices.&lt;/p&gt;

&lt;p&gt;These don’t directly affect Core Web Vitals, but they’re key for overall user experience.&lt;/p&gt;


&lt;h2&gt;
  
  
  🚀 How to Improve Your Scores
&lt;/h2&gt;

&lt;p&gt;Improving your Lighthouse performance score doesn't mean rewriting your entire site, many optimizations are small tweaks that can have a big impact. Let’s dive deeper into the most effective techniques and how they help your metrics.&lt;/p&gt;
&lt;h3&gt;
  
  
  Optimize Images
&lt;/h3&gt;

&lt;p&gt;Images often make up the bulk of a page’s weight. If they’re not optimized, they can slow down your site dramatically.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Use modern formats like WebP or AVIF:&lt;/strong&gt; These formats offer better compression than traditional formats like JPEG or PNG, reducing file sizes without losing quality.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Resize images to match display sizes:&lt;/strong&gt; Don’t load a 5000px-wide image if it’s only going to show at 300px.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Metrics impacted: Largest Contentful Paint (LCP), Speed Index&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;
  
  
  Reduce and Split Your JavaScript
&lt;/h3&gt;

&lt;p&gt;JavaScript is powerful, but too much of it can cause delays in loading and make the browser unresponsive.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Bundle splitting:&lt;/strong&gt; Tools like Webpack, Vite, or Next.js allow you to split your code into smaller chunks that are loaded only when needed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Tree shaking:&lt;/strong&gt; Remove unused code from third-party libraries during bundling.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Avoid unnecessary frameworks or heavy dependencies:&lt;/strong&gt; Sometimes vanilla JS or lighter libraries can do the same job.&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// webpack.config.js&lt;/span&gt;
&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;main&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./src/index.js&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;optimization&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;splitChunks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;chunks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;all&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="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// Only importing what you need&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;debounce&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;lodash-es&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Instead of a full UI framework, use vanilla:&lt;/span&gt;
&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#btn&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;click&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Clicked!&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;blockquote&gt;
&lt;p&gt;Metrics impacted: Total Blocking Time (TBT), Time to Interactive (TTI)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;
  
  
  Use Lazy Loading
&lt;/h3&gt;

&lt;p&gt;Lazy loading defers the loading of non-critical content, like images below the fold, until the user is about to see them.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add the &lt;code&gt;loading="lazy"&lt;/code&gt; attribute to &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;iframe&amp;gt;&lt;/code&gt; elements.&lt;/li&gt;
&lt;li&gt;For background images or custom components, you can implement lazy loading with JavaScript.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This helps reduce the initial load size, speeding up the time it takes for your page to become interactive.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"photo.jpg"&lt;/span&gt; &lt;span class="na"&gt;loading=&lt;/span&gt;&lt;span class="s"&gt;"lazy"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"Lazy-loaded photo"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;iframe&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"video.html"&lt;/span&gt; &lt;span class="na"&gt;loading=&lt;/span&gt;&lt;span class="s"&gt;"lazy"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/iframe&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Metrics impacted: First Contentful Paint (FCP), Speed Index, LCP&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Avoid Render-Blocking Resources
&lt;/h3&gt;

&lt;p&gt;Render-blocking resources delay how quickly the browser can start rendering the page. These usually include large CSS files or scripts loaded in the &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Minify and inline critical CSS&lt;/strong&gt; to reduce blocking.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Defer non-essential JS&lt;/strong&gt; using the &lt;code&gt;defer&lt;/code&gt; or &lt;code&gt;async&lt;/code&gt; attributes.&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;font-display: swap&lt;/code&gt; for web fonts to avoid text invisibility.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Metrics impacted: FCP, TTI, TBT&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Enable Caching
&lt;/h3&gt;

&lt;p&gt;Caching stores files locally so they don’t need to be downloaded again on future visits.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use HTTP cache headers like &lt;code&gt;Cache-Control&lt;/code&gt; or &lt;code&gt;ETag&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Serve assets with hashed filenames (e.g., &lt;code&gt;style.abc123.css&lt;/code&gt;) so browsers can cache them safely.&lt;/li&gt;
&lt;li&gt;Use a service worker (especially for PWAs) to cache offline-friendly resources.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Metrics impacted: Repeat view performance, Time to Interactive, Speed Index&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;By applying these strategies, you're not just improving your Lighthouse score, but you’re making your site smoother, more responsive, and more enjoyable for everyone who visits.&lt;/p&gt;

&lt;p&gt;Even small changes can lead to meaningful gains in user experience, which ultimately means better engagement, higher retention, and stronger SEO.&lt;/p&gt;

</description>
      <category>lighthouse</category>
      <category>webdev</category>
      <category>seo</category>
      <category>performance</category>
    </item>
    <item>
      <title>Hosting web app on your old Android phone</title>
      <dc:creator>Guilherme Araujo</dc:creator>
      <pubDate>Sun, 20 Apr 2025 22:47:36 +0000</pubDate>
      <link>https://dev.to/quave/hosting-web-app-on-your-old-android-phone-54bg</link>
      <guid>https://dev.to/quave/hosting-web-app-on-your-old-android-phone-54bg</guid>
      <description>&lt;p&gt;Recently, I was developing a simple bot to interact with a WhatsApp group. The code was pretty straightforward: a webhook that would read messages from the app and save data to a MongoDB database. As I continued working on the bot, I realized I needed to learn more about deploying such applications in real-world environments. To do this, I decided I wanted to self-host the application on a local server, like a Raspberry Pi, and started researching different models and their prices.&lt;/p&gt;

&lt;p&gt;However, to my surprise, the prices for these devices had significantly increased due to a global chip shortage and the rising demand for Raspberry Pis. After spending some time looking at the inflated prices, I grew frustrated and began considering alternative solutions. That's when it hit me: I have an old Android phone – a Galaxy S9 – which is still quite powerful and functional even by today’s standards. Since it’s an Android, I wondered, could I run Linux on it?&lt;/p&gt;

&lt;p&gt;Curious to explore this possibility, I began researching how I could run a Node.js application on my phone. Spoiler alert: it worked!&lt;/p&gt;

&lt;p&gt;In this article, I’ll walk you through how I managed to turn my Galaxy S9 into a fully functional Node.js server using Termux. Along the way, I learned how Termux transforms an Android device into a powerful Linux environment, and how you can leverage your old phone as a local server for development or even small-scale production tasks. This setup can be incredibly useful if you’re looking to experiment or deploy projects without investing in extra hardware.&lt;/p&gt;

&lt;h3&gt;
  
  
  Installing &lt;strong&gt;Termux&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The first step is to install Termux, which is a powerful terminal emulator for Android that provides a Linux-like environment.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Go to the Play Store on your Android phone and install &lt;strong&gt;Termux&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Opening &lt;strong&gt;Termux&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Once installed, open the Termux app, and let’s start by updating all the Termux packages:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pkg update
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Setting Up SSH Access
&lt;/h3&gt;

&lt;p&gt;To make things easier and avoid constantly typing on the phone’s small keyboard, I decided to set up &lt;strong&gt;SSH&lt;/strong&gt; so that I could access the phone remotely from my computer.&lt;/p&gt;

&lt;p&gt;1- Install the &lt;code&gt;openssh&lt;/code&gt; package:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pkg &lt;span class="nb"&gt;install &lt;/span&gt;openssh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;2- Start the SSH server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;sshd
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;3- Find the Termux IP address:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ifconfig
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;4- Find the Termux username:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;whoami&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;5- Set a password for SSH access:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;passwd
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, from your computer, you can connect to your phone via SSH:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh &amp;lt;username&amp;gt;@&amp;lt;Termux_IP_address&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At this point, you have a fully functional Linux environment running on your phone, and you can access it remotely via SSH.&lt;/p&gt;

&lt;p&gt;Optionally, you can install &lt;strong&gt;tmux&lt;/strong&gt;, a terminal multiplexer, which allows you to execute multiple applications in the same terminal session. I used &lt;strong&gt;tmux&lt;/strong&gt; to manage tasks like port forwarding and running the Node.js application simultaneously.&lt;/p&gt;

&lt;h3&gt;
  
  
  Setting Up a Cloudflare Tunnel
&lt;/h3&gt;

&lt;p&gt;To expose your application to the internet, you can use &lt;strong&gt;Cloudflare Tunnel&lt;/strong&gt;. This will create a secure connection between your local server and the internet, making your Node.js application accessible.&lt;/p&gt;

&lt;p&gt;1- Install &lt;strong&gt;cloudflared&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pkg &lt;span class="nb"&gt;install &lt;/span&gt;cloudflared
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;2- Run the following command to create a tunnel for your application:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;cloudflared tunnel &lt;span class="nt"&gt;--url&lt;/span&gt; http://localhost:3000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once the tunnel is running, you’ll be provided with a public URL that you can use to access your API from anywhere.&lt;/p&gt;

&lt;h3&gt;
  
  
  Installing Node.js
&lt;/h3&gt;

&lt;p&gt;Termux makes it incredibly easy to install &lt;strong&gt;Node.js&lt;/strong&gt; and start building applications.&lt;/p&gt;

&lt;p&gt;1- To install Node.js, simply run the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pkg &lt;span class="nb"&gt;install &lt;/span&gt;nodejs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;2- Once Node.js is installed, you can start your Node.js application and expose it to the internet using the Cloudflare tunnel we set up earlier.&lt;/p&gt;

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

&lt;p&gt;After completing these steps, my Node.js application was successfully running and publicly accessible, all from my old Android phone! I was able to deploy my bot, which interacted with the WhatsApp group and stored data in MongoDB, directly from my phone. This setup is surprisingly powerful and proves that you don’t need expensive hardware to host applications; an old Android phone can easily do the job.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Optimizing End-to-End Testing: Strategies for Speed, Reliability, and Efficiency</title>
      <dc:creator>Guilherme Araujo</dc:creator>
      <pubDate>Mon, 27 Jan 2025 18:04:55 +0000</pubDate>
      <link>https://dev.to/quave/optimizing-end-to-end-testing-strategies-for-speed-reliability-and-efficiency-1idh</link>
      <guid>https://dev.to/quave/optimizing-end-to-end-testing-strategies-for-speed-reliability-and-efficiency-1idh</guid>
      <description>&lt;h1&gt;
  
  
  Best Practices for Efficient E2E Testing
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Quick Overview: What Are E2E Tests?
&lt;/h2&gt;

&lt;p&gt;End-to-End (E2E) tests are designed to run on top of your application, simulating real user interactions such as clicking buttons, typing input, navigating between pages, and more.&lt;/p&gt;

&lt;p&gt;These tests are extremely useful for checking that entire workflows work as expected. For example, in an eCommerce application, an E2E test could simulate a complete purchase journey: selecting a product, adding it to the cart, registering a credit card, and completing the checkout process. By testing real-world scenarios, E2E tests help ensure your application's key features work well together.&lt;/p&gt;




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

&lt;p&gt;Recently, in my current project, we faced the task of restoring some old, skipped E2E tests. While working through them, we observed several opportunities for improvement. Many of these tests could be merged or rewritten in a more efficient way, and we realized that our approach of restoring the database for every test was significantly increasing the execution time.&lt;/p&gt;

&lt;p&gt;Additionally, we identified potential to parallelize some of the test scenarios, which could further optimize our testing process. These observations led us to focus on techniques to improve performance, such as merging and optimizing test cases, leveraging parallelization, and rethinking our database restoration strategy. In this article, I'll share these strategies, primarily based on my experience using Playwright as an E2E testing tool. However, these techniques are likely applicable to most E2E testing frameworks.&lt;/p&gt;




&lt;h2&gt;
  
  
  Test Parallelization
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Parallelization Across Files
&lt;/h3&gt;

&lt;p&gt;Parallelizing tests is one of the most effective ways to speed up E2E test execution, especially as your test suite grows. By running multiple tests simultaneously, you can utilize your system's resources more efficiently and significantly reduce the total runtime.&lt;/p&gt;

&lt;p&gt;In our project, we configured Playwright to use 5 workers by default. Each worker runs a test file independently, enabling up to 5 tests to execute at the same time. Here's how we set it up:&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;// playwright.config.js  &lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;defineConfig&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@playwright/test&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nf"&gt;defineConfig&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;  
  &lt;span class="na"&gt;workers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
&lt;span class="p"&gt;});&lt;/span&gt;  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This simple change led to a significant improvement in test execution speed, as multiple tests could run concurrently.&lt;/p&gt;

&lt;p&gt;However, some tests required rewriting due to side effects. For instance, certain tests created or modified resources that other tests depended on. When these tests ran in parallel, their execution order sometimes caused failures, as the shared state was not properly managed.&lt;/p&gt;




&lt;h3&gt;
  
  
  Parallelizing Tests Within Files
&lt;/h3&gt;

&lt;p&gt;In addition to parallelizing tests across multiple files, we found that it’s also possible to enable parallel execution within a single test file. This approach is especially useful when you have multiple independent tests grouped in the same file and want to further optimize execution time.&lt;/p&gt;

&lt;p&gt;In Playwright, this can be achieved by wrapping your tests in &lt;code&gt;test.describe.parallel&lt;/code&gt;. All tests inside this block will execute simultaneously:&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;test&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parallel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Group of parallel tests&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
  &lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Test 1&lt;/span&gt;&lt;span class="dl"&gt;'&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;page&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="c1"&gt;// Test logic here  &lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;  

  &lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Test 2&lt;/span&gt;&lt;span class="dl"&gt;'&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;page&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="c1"&gt;// Test logic here  &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 our experience parallelizing tests across files, the key principles remain the same:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Avoid Side Effects:&lt;/strong&gt; Ensure that tests are fully independent and do not share or modify resources in a way that could interfere with other tests;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reuse Resources Wisely:&lt;/strong&gt; Manage shared resources, such as browser instances or test data, efficiently to prevent contention or conflicts during parallel execution.
This technique can deliver a noticeable speedup for large test files, but it also requires careful planning to maintain test reliability and avoid flaky results. By isolating tests and managing resources effectively, you can take full advantage of parallel execution within files.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Pre-Authentication
&lt;/h3&gt;

&lt;p&gt;Pre-authentication is a critical step to ensure that each test begins with a consistent, valid user session. This technique eliminates the need to repeatedly perform login actions for every test, significantly improving both speed and reliability in the tests, especially when tests are executed in parallel.&lt;/p&gt;

&lt;p&gt;The approach involves leveraging Playwright’s ability to work with &lt;code&gt;storageState&lt;/code&gt;, which stores session information (e.g., cookies, local storage) for pre-authenticated users. By restoring this state at the beginning of each test, the user is already logged in, allowing tests to focus on verifying functionality rather than navigating login flows.&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;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;User View - TEST_ID#153&lt;/span&gt;&lt;span class="dl"&gt;'&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;browser&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;context&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;browser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;newContext&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;storageState&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;__dirname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;`../.auth/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.json`&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="c1"&gt;// Pre-authenticated session&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;page&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;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;newPage&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;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;goto&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;// User is already logged in at this point&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This approach guarantees that each test operates in isolation, preventing cross-contamination of session data. The pre-authenticated &lt;code&gt;storageState&lt;/code&gt; ensures that tests skip redundant login steps, saving valuable time while maintaining consistency across the suite.&lt;/p&gt;

&lt;p&gt;Of course, there are challenges to consider, such as ensuring that the &lt;code&gt;.auth/${email}.json&lt;/code&gt; files are consistently updated with valid session data. Additionally, it's important to focus on the reusability of helper functions, avoiding tightly coupled data or risky code that could compromise the maintainability and reliability of the test suite.&lt;/p&gt;




&lt;h3&gt;
  
  
  Best Practices for Efficient E2E Testing
&lt;/h3&gt;

&lt;p&gt;To maximize the efficiency of your E2E tests:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Prioritize Test Isolation:&lt;/strong&gt; Ensure that tests are independent and avoid shared state wherever possible;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Minimize Dependencies:&lt;/strong&gt; Pre-authentication and reusable helpers can reduce redundancy and improve test reliability;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Monitor Pipeline Performance:&lt;/strong&gt; Regularly review test runtimes and resource utilization to identify bottlenecks or opportunities for optimization;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Balance Coverage and Execution Time:&lt;/strong&gt; Focus on covering critical workflows without overloading the pipeline with unnecessary tests.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By adhering to these best practices, you can build a robust, scalable, and efficient E2E testing framework that delivers reliable results while saving time and resources.&lt;/p&gt;




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

&lt;p&gt;Optimizing E2E tests is an ongoing process that involves balancing performance, reliability, and coverage. By leveraging techniques like test parallelization, pre-authentication, and careful resource management, you can significantly improve test execution times without compromising accuracy. While challenges such as side effects and maintaining reusable code require attention, the benefits of a well-optimized E2E suite far outweigh the effort. These practices, when implemented thoughtfully, pave the way for a more efficient and reliable testing process, enabling faster delivery of high-quality software.&lt;/p&gt;

</description>
      <category>playwright</category>
      <category>javascript</category>
      <category>webdev</category>
      <category>frontend</category>
    </item>
    <item>
      <title>Handling Promises with Higher-Order Functions in JavaScript</title>
      <dc:creator>Guilherme Araujo</dc:creator>
      <pubDate>Tue, 17 Dec 2024 16:45:50 +0000</pubDate>
      <link>https://dev.to/quave/handling-promises-with-higher-order-functions-in-javascript-3apk</link>
      <guid>https://dev.to/quave/handling-promises-with-higher-order-functions-in-javascript-3apk</guid>
      <description>&lt;p&gt;When working with arrays in JavaScript, you may find yourself needing to make asynchronous calls inside methods like &lt;code&gt;forEach&lt;/code&gt;, &lt;code&gt;.map&lt;/code&gt;, or similar functions. But after encountering errors or unexpected outputs, you might wonder, &lt;em&gt;Why isn’t this working as expected?&lt;/em&gt; In this article, we’ll dive into these situations and explore how to handle promises effectively within higher-order functions.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is a higher-order function?
&lt;/h3&gt;

&lt;p&gt;Starting from the beginning:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A higher order function is a function that takes one or more functions as arguments, or returns a function as its result.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A simple example would look 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="c1"&gt;// Higher-order function that returns a function&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;createAdder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;y&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;x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;addFive&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createAdder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;addFive&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="c1"&gt;// Console output: 8&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  What is a Promise?
&lt;/h3&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;A &lt;strong&gt;Promise&lt;/strong&gt; is an object representing a value that may not be available yet but will be resolved in the future. Promises allow you to attach handlers to manage the eventual success or failure of an asynchronous operation, making it easier to handle responses as they arrive.&lt;/p&gt;

&lt;p&gt;This pattern is especially useful in cases like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;API calls&lt;/strong&gt;: When fetching data from external sources, such as RESTful APIs, the data may take time to arrive;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Database interactions&lt;/strong&gt;: Querying a database can also be time-consuming, so promises allow you to handle the data only once it’s available.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Instead of returning the final data instantly, these asynchronous functions return a promise, which acts as a placeholder for the value that will be provided later.&lt;/p&gt;

&lt;p&gt;Given these two concepts, let’s see how they interact.&lt;/p&gt;

&lt;h3&gt;
  
  
  Combining Promises with Higher-Order Functions: Practical Examples
&lt;/h3&gt;

&lt;p&gt;Now that we understand promises, let’s look at a common use case: fetching data, such as retrieving user information from an array of user IDs:&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;userIds&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="c1"&gt;// Simulated async function to fetch user data&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fetchUser&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="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="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="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="s2"&gt;`User &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; data`&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="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;&lt;strong&gt;❌ The Common Mistake: Not Handling the Array of Promises Properly&lt;/strong&gt;&lt;br&gt;
When using &lt;code&gt;.map&lt;/code&gt; with an asynchronous function, a common mistake is forgetting that map will immediately return an array of promises instead of resolved values. Without additional handling, this leads to unexpected 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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;wrongWay&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="c1"&gt;// This creates an array of promises, not resolved values!&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;users&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;userIds&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&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;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetchUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Output: [Promise, Promise, Promise]&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;In this example, each call to fetchUser(id) returns a promise, so map returns an array of promises rather than the final data values. Simply awaiting inside &lt;code&gt;.map&lt;/code&gt; doesn’t resolve the array itself; instead, it just creates a promise for each item in the array.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;✅ The Correct Approach: Using Promise.all with map&lt;/strong&gt;&lt;br&gt;
To properly handle an array of promises, you need to use Promise.all. This method takes an array of promises and returns a new promise that resolves once all the promises in the array are fulfilled. Here’s how to use Promise.all to get the resolved data:&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;rightWay&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;users&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;userIds&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;fetchUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Output: ["User 1 data", "User 2 data", "User 3 data"]&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  .filter function
&lt;/h3&gt;

&lt;p&gt;Like &lt;code&gt;.map&lt;/code&gt;, the &lt;code&gt;.filter&lt;/code&gt; function can lead to unexpected behavior when combined with asynchronous functions. Suppose we want to filter an array of user IDs to retrieve only the IDs of users that meet certain criteria, such as users with IDs that are "active."&lt;/p&gt;

&lt;p&gt;Let’s take a look at a common mistake and how to avoid it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;❌ The Common Mistake: Using .filter with Async Functions&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isActiveUser&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="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="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="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// Simulates checking if a user is active&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;id&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="c1"&gt;// Returns true for even IDs, false for odd ones&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;const&lt;/span&gt; &lt;span class="nx"&gt;wrongFilterUsage&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;activeUsers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;userIds&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&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;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;isActiveUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;activeUsers&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Output: [1, 2, 3] — the original array, not the filtered results&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;In this example, &lt;code&gt;.filter&lt;/code&gt; doesn’t wait for &lt;code&gt;isActiveUser(id)&lt;/code&gt; to resolve, so it operates on the original array of IDs rather than the resolved results. The array &lt;code&gt;activeUsers&lt;/code&gt; ends up containing all user IDs, regardless of whether they are active, because the async function inside &lt;code&gt;.filter&lt;/code&gt; doesn’t return the expected boolean.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;✅ The Correct Approach: Using Promise.all with .map and .filter&lt;/strong&gt;&lt;br&gt;
To properly filter an array with an async function, we need to use &lt;code&gt;.map&lt;/code&gt; in combination with &lt;code&gt;Promise.all&lt;/code&gt; to resolve all promises first, then apply &lt;code&gt;.filter&lt;/code&gt; on the resolved values. Here’s the correct approach:&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;correctFilterUsage&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="c1"&gt;// Use Promise.all to resolve the async checks for each user ID&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;userIds&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&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;id&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;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;isActive&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;isActiveUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&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;// Filter based on the resolved isActive status&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;activeUsers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;results&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isActive&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&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;activeUsers&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Output: [2] — only active user IDs&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;💡Promise.all&lt;/strong&gt;&lt;br&gt;
Using Promise.all offers several advantages for handling asynchronous tasks, especially when working with multiple promises simultaneously: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Parallel Execution of Requests&lt;/strong&gt;: One of the primary benefits of Promise.all is its ability to execute multiple promises in parallel. When you pass an array of promises to &lt;code&gt;Promise.all&lt;/code&gt;, it initiates all of them at the same time, allowing each promise to start processing concurrently. This can greatly improve performance by reducing the overall wait time, as all tasks are "in progress" together.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Example: If you’re fetching data for multiple users or making multiple API requests, Promise.all allows you to start each request without waiting for others to finish. This is particularly valuable for tasks where the order of execution doesn’t matter, like retrieving data from different sources.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;⚠️ &lt;strong&gt;Caution&lt;/strong&gt;: Use &lt;code&gt;Promise.all&lt;/code&gt; carefully, as parallel execution may not always be ideal. For cases where tasks depend on one another or need to run sequentially (e.g., writing to a database in a specific order), parallel execution may cause issues. We’ll explore sequential handling methods later on.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Simplified Error Handling&lt;/strong&gt;: Another powerful feature of &lt;code&gt;Promise.all&lt;/code&gt; is its error-handling mechanism. If any promise in the array rejects, &lt;code&gt;Promise.all&lt;/code&gt; will immediately reject with that error, allowing you to handle failures in a single &lt;code&gt;.catch&lt;/code&gt; block. This makes error management more streamlined and efficient.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: Only the first rejection triggers the error; the remaining promises will continue to execute but won’t trigger further &lt;code&gt;.catch&lt;/code&gt; blocks. If you need to capture each promise's result regardless of failure, consider using &lt;code&gt;Promise.allSettled&lt;/code&gt;, which returns an array of outcomes for each promise, detailing whether they resolved or rejected.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Aggregated Results&lt;/strong&gt;: Once all promises in &lt;code&gt;Promise.all&lt;/code&gt; resolve, it returns an array of the resolved values, &lt;u&gt;matching the order of the original promises&lt;/u&gt;. This makes it easy to work with the final results in a predictable way, even though each promise completes independently.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Summary Table
&lt;/h3&gt;

&lt;p&gt;There are a lot of higher-order functions available in JavaScript, but here is a attempt to create a cheat sheet to make it easier to remember how the most common functions deal with asynchronous operations:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Method&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Common Issue&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Correct Solution&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;.filter&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Returns array of promises&lt;/td&gt;
&lt;td&gt;Use &lt;code&gt;Promise.all&lt;/code&gt; with &lt;code&gt;.map&lt;/code&gt;, then filter synchronously&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;.forEach&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Doesn’t wait for async functions to complete&lt;/td&gt;
&lt;td&gt;Use &lt;code&gt;Promise.all&lt;/code&gt; with &lt;code&gt;.map&lt;/code&gt; (parallel) or &lt;code&gt;for...of&lt;/code&gt; with &lt;code&gt;await&lt;/code&gt; (sequential)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;.find&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Doesn’t wait for async condition to resolve&lt;/td&gt;
&lt;td&gt;Use &lt;code&gt;for...of&lt;/code&gt; with &lt;code&gt;await&lt;/code&gt; to find the first match sequentially&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;.reduce&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Returns promise for each iteration&lt;/td&gt;
&lt;td&gt;Use async &lt;code&gt;reduce&lt;/code&gt;, awaiting the accumulator before each iteration&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h2&gt;
  
  
  for...of for Sequential Async Processing
&lt;/h2&gt;

&lt;p&gt;As mentioned earlier, simultaneous processing isn’t always ideal, especially when tasks depend on each other or could overload a server or API. In such cases, handling tasks sequentially can be beneficial, as it ensures that each task completes before the next one begins.&lt;/p&gt;

&lt;p&gt;This is where the &lt;code&gt;for...of&lt;/code&gt; loop becomes valuable. Unlike &lt;code&gt;.map&lt;/code&gt; or &lt;code&gt;.forEach&lt;/code&gt;, &lt;code&gt;for...of&lt;/code&gt; allows you to &lt;code&gt;await&lt;/code&gt; each asynchronous operation in sequence, ensuring that each task completes before moving on to the next. This approach is particularly useful in situations like making API calls that should occur in a specific order, processing a list of database writes sequentially, or handling rate-limited operations where triggering requests all at once could lead to errors.&lt;/p&gt;

&lt;p&gt;An example of &lt;code&gt;for...of&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;userIds&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="c1"&gt;// Async function that simulates an API call&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fetchUserData&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="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="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="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="s2"&gt;`User &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; data`&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="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;fetchAllUserData&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;userData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;

  &lt;span class="k"&gt;for &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;id&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;userIds&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;data&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;fetchUserData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Each call waits for the previous one to complete&lt;/span&gt;
    &lt;span class="nx"&gt;userData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&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="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;userData&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Output: ["User 1 data", "User 2 data", "User 3 data"]&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nf"&gt;fetchAllUserData&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, each &lt;code&gt;fetchUserData&lt;/code&gt; call only starts after the previous one finishes, ensuring the operations are processed sequentially.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping Everything up
&lt;/h2&gt;

&lt;p&gt;Working with asynchronous operations inside &lt;strong&gt;higher-order&lt;/strong&gt; functions can be tricky and often leads to misunderstandings and unexpected results. Each method—whether &lt;code&gt;.map&lt;/code&gt;, &lt;code&gt;.filter&lt;/code&gt;, &lt;code&gt;.forEach&lt;/code&gt;, &lt;code&gt;.find&lt;/code&gt;, or &lt;code&gt;.reduce&lt;/code&gt; —behaves differently with async functions, and recognizing these nuances is key to avoiding common mistakes. By understanding how each function handles promises and when to use tools like &lt;code&gt;Promise.all&lt;/code&gt; or the &lt;code&gt;for...of&lt;/code&gt; loop, you can significantly improve both the readability and reliability of your asynchronous code.&lt;/p&gt;

&lt;p&gt;Hopefully, this guide will help clarify any questions that arise about how functions and promises behave in different scenarios.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Common Mistakes of a Developer Starting with Meteor.js</title>
      <dc:creator>Guilherme Araujo</dc:creator>
      <pubDate>Mon, 28 Oct 2024 20:45:42 +0000</pubDate>
      <link>https://dev.to/quave/common-mistakes-of-a-developer-starting-with-meteorjs-4775</link>
      <guid>https://dev.to/quave/common-mistakes-of-a-developer-starting-with-meteorjs-4775</guid>
      <description>&lt;p&gt;After nearly two months of working with Meteor.js, I find it valuable to document some of the most common mistakes I've made while using the framework. In this article, I’ll delve into the typical errors and questions I've encountered from fellow beginners, aiming to provide insights that can help others avoid the same pitfalls.&lt;/p&gt;

&lt;h2&gt;
  
  
  Poor optimized and unsafe Publications
&lt;/h2&gt;

&lt;p&gt;On my first publication I've created a code 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="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Events&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Mongo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Collection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;events&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;Meteor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;publish&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;events.list&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;Events&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&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 above, we create a collection called events and then declare a publication called events.list that returns a &lt;a href="https://v3-docs.meteor.com/api/collections.html#mongo-cursor" rel="noopener noreferrer"&gt;collection cursor&lt;/a&gt; to the &lt;strong&gt;entire collection with all its fields&lt;/strong&gt;. Once the client subscribes to it, all this data will be sent to the client and will be monitored for any updates that occur in the collection.&lt;/p&gt;

&lt;p&gt;Although it might seem like magic, this reactivity comes with a significant computational cost. The system has to &lt;strong&gt;monitor the entire collection, compare the differences between new and old data, and update the client with each change.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Optimizing your Publication
&lt;/h3&gt;

&lt;p&gt;To create performatic and optimized queries we need to understand some concepts about the publications we create:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Use Filters to Retrieve Relevant Data:&lt;/strong&gt; Applying filters in your &lt;code&gt;find({ })&lt;/code&gt; queries is &lt;strong&gt;crucial&lt;/strong&gt; for ensuring that only relevant data is retrieved from the database. Filters allow you to precisely define the subset of data you want to fetch, based on conditions such as user ID, date range, or any other criteria. By doing so, you avoid retrieving unnecessary or irrelevant records (e.g., data belonging to other users or outdated entries), which could unnecessarily increase the amount of data sent to the client.&lt;br&gt;
Well-designed filters not only enhance security by ensuring that users only receive their own data but also reduce both server load and network traffic by minimizing the data processed and transmitted;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Leverage Projections for Fine-Grained Control:&lt;/strong&gt; Projections allow you to retrieve only the specific fields you need from your documents, instead of sending the entire document to the client. This prevents large, unnecessary objects from being transferred and reduces memory overhead on the client-side. By sending only the essential fields, you also optimize memory usage and minimize the load on the client's processing.&lt;br&gt;
For example, if you only need the name and date of the event, you can write:&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;Meteor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;publish&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;events.list&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; 
  &lt;span class="nx"&gt;Events&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&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="na"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;:&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="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;date&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="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Paginate Large Data Sets:&lt;/strong&gt; If you are working with large data sets, consider implementing pagination. This allows you to send data in smaller, more manageable chunks, improving performance and providing a smoother user experience;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Security - Protect Sensitive Data:&lt;/strong&gt; Publishing entire collections without any restrictions can unintentionally expose sensitive data from your application. This is a significant security risk. By applying filters and projections, you can control exactly what data is sent to the client, ensuring that only the necessary and non-sensitive information is exposed. This practice not only optimizes performance but also safeguards your application by preventing unintended data leaks.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After passing thru all these concepts, now we can refactor our initial subscription:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;check&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;meteor/check&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;Meteor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;publish&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;events.list&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&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;userId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ready&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Stop publication if the user is not authenticated&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;check&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;Number&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="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;page&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;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;LIMIT&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="c1"&gt;// Calculate how many documents to skip based on the page number&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;skip&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;page&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;LIMIT&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;Events&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;userId&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;userId&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="c1"&gt;// filter by current user's events&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;:&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="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;date&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;// only return necessary fields&lt;/span&gt;
      &lt;span class="na"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;LIMIT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;                 &lt;span class="c1"&gt;// limit the number of documents returned&lt;/span&gt;
      &lt;span class="na"&gt;skip&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;skip&lt;/span&gt;                    &lt;span class="c1"&gt;// skip documents based on page number&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;h2&gt;
  
  
  Too much reactivity - useSubscribe everywhere
&lt;/h2&gt;

&lt;p&gt;As mentioned earlier, leveraging subscriptions in Meteor.js can feel like magic, providing you with reactive data on the front-end with minimal effort. However, over-relying on this feature can lead to messy, hard-to-debug, and inconsistent code.&lt;/p&gt;

&lt;p&gt;When a document is published by the back-end and you subscribe to it on the front-end, the data is stored in a client-side in-memory database called &lt;a href="https://github.com/mWater/minimongo" rel="noopener noreferrer"&gt;minimongo&lt;/a&gt;. This allows you to easily access data using &lt;code&gt;Collection.find({})&lt;/code&gt; or &lt;code&gt;Collection.findOne({})&lt;/code&gt;. But as your project scales and multiple components manage the same data, this can become complicated.&lt;/p&gt;

&lt;p&gt;For instance, consider a details page that follows a listing. If your subscription is placed within the listing component and a user navigates directly to the details page via the URL, the required data may not be available for display.&lt;/p&gt;

&lt;p&gt;To avoid this issue, it’s essential to understand where data is being used and to evaluate whether it truly needs to be reactive. Using Meteor methods allows you to fetch data like a standard HTTP call from your back-end, eliminating the guesswork about data availability. This approach not only simplifies data management but also enhances performance by reducing unnecessary reactivity, leading to cleaner and more maintainable code.&lt;/p&gt;

&lt;h3&gt;
  
  
  Data Merge Issues
&lt;/h3&gt;

&lt;p&gt;One common challenge in Meteor.js arises from managing multiple subscriptions, especially when dealing with overlapping data. This can often occur due to an excessive number of subscriptions or a misunderstanding of how publications work.&lt;/p&gt;

&lt;p&gt;Consider the following example, where two subscriptions pull different fields from the same collection:&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;return&lt;/span&gt; &lt;span class="nx"&gt;Events&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;({},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;date&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="na"&gt;host&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="p"&gt;});&lt;/span&gt;
&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;Events&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;({},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;host.name&lt;/span&gt;&lt;span class="dl"&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="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On the client side, Meteor only maintains a single copy of each document, regardless of how many subscriptions exist. The server determines which fields to send to the client using a mechanism called the 'MergeBox'. Ideally, with both of these subscriptions active, the client would have the complete &lt;code&gt;host&lt;/code&gt; data, since one subscription provides the full &lt;code&gt;host&lt;/code&gt; object and the other supplies only a partial view.&lt;/p&gt;

&lt;p&gt;However, the MergeBox operates only at the top field level, as explained in Meteor's documentation:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If more than one subscription sends conflicting values for a field (same collection name, document ID, and field name), then the value on the client will be one of the published values, chosen arbitrarily.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This means documents aren’t deeply merged. Sometimes, the full host from the first publication will be displayed, while other times, the client may receive only the partial host.name from the second publication, leading to inconsistent data on the front-end.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sorting in Publications
&lt;/h2&gt;

&lt;p&gt;When a client subscribes to a publication, the data it receives is merged with existing data in the client’s minimongo store. This merging process doesn’t always respect the original sorting order from the server, which can result in records being displayed in an incorrect order.&lt;/p&gt;

&lt;p&gt;To avoid this, it's often unnecessary to handle sorting within the publication itself unless the order of the data is dynamic (e.g., for pagination or live updates). Instead, you can delegate sorting to the front-end when retrieving data from minimongo. This ensures the data is always presented in the desired order without risking a mix-up due to how subscriptions are processed.&lt;/p&gt;

&lt;p&gt;For example, you can apply sorting directly when querying your local collection on the client:&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;Events&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;({},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;date&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&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;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Working with &lt;code&gt;Meteor.js&lt;/code&gt; offers a powerful and flexible way to build &lt;strong&gt;real-time applications&lt;/strong&gt;, but like any framework, it comes with its own set of challenges. Through my experience, I’ve learned that understanding the inner workings of &lt;u&gt;subscriptions, data reactivity, and minimongo&lt;/u&gt; is crucial for avoiding common pitfalls. Over-reliance on reactivity can lead to performance issues, and managing multiple subscriptions without proper planning can cause data inconsistencies.&lt;/p&gt;

&lt;p&gt;By taking control of data flow—whether by strategically using Meteor methods for non-reactive data, managing data subscriptions at higher levels, or handling sorting on the client side—you can ensure cleaner, more maintainable code. With careful consideration of these practices, your Meteor.js projects will not only perform better but also be easier to debug and scale.&lt;/p&gt;

&lt;p&gt;Special thanks to my teammates João Ladeira, Isaque, and Renan for helping me understand these concepts and rescuing me from these pitfalls.&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
