<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
	<title>Carlos Molina</title>
	<subtitle>My personal blog of the things I am learning</subtitle>
	
	<link href="https://cmolina.dev/feed/feed.xml" rel="self"/>
	<link href="https://cmolina.dev"/>
	<updated>2024-05-22T00:00:00Z</updated>
	<id>https://cmolina.dev</id>
	<author>
		<name>Carlos Andrés Molina Avendaño</name>
		<email></email>
	</author>
	
	<entry>
		<title>Using images for every resolution</title>
		<link href="https://cmolina.dev/posts/2019/07/images-for-every-resolution/"/>
		<updated>2019-07-08T00:00:00Z</updated>
		<id>https://cmolina.dev/posts/2019/07/images-for-every-resolution/</id>
		<content type="html">
		  &lt;p&gt;A couple of days ago I needed to add an icon next to a text into a website I&#39;ve been working on.&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;img&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;really-big-icon.png&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;alt&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It was really easy and everything looks nice.&lt;/p&gt;
&lt;p&gt;But then, a coworker mentioned that I was delivering a really big file for this small icon. Indeed, by the styles the icon size should be &lt;strong&gt;25px height&lt;/strong&gt;, and the original icon was &lt;strong&gt;150px&lt;/strong&gt;. So I went ahead, resize the icon an updated the URL&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;img&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;icon-25.png&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;alt&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;but this time, the icon looked plain bad on my screen. &lt;em&gt;—What&#39;s wrong?&lt;/em&gt; I wonder myself.&lt;/p&gt;
&lt;h2 id=&quot;high-density-screens&quot;&gt;High-density screens &lt;a class=&quot;direct-link&quot; href=&quot;https://cmolina.dev/posts/2019/07/images-for-every-resolution/#high-density-screens&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;After a bit of search, I realized I was using a high-density screen. In particular, I&#39;ve been using a somewhat recently MacBook Pro that has a Retina display, which provides a really crispy image all the time —but not now.&lt;/p&gt;
&lt;p&gt;The solution I found implies using the &lt;code&gt;srcset&lt;/code&gt; attribute with a list of higher resolution images separated by commas, and let the browser choose what is best for the current screen. In my case, it looked like this&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;img&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token attr-name&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;icon-25.png&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token attr-name&quot;&gt;srcset&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;icon-25.png 1x, icon-50.png 2x&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token attr-name&quot;&gt;alt&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But I still didn&#39;t understand why should I provide an image with the double of the pixels. Pixels are pixels. Right?&lt;/p&gt;
&lt;h2 id=&quot;css-px&quot;&gt;&amp;quot;CSS px&amp;quot; &lt;a class=&quot;direct-link&quot; href=&quot;https://cmolina.dev/posts/2019/07/images-for-every-resolution/#css-px&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;So I kept reading and I found an interesting article &lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://cmolina.dev/posts/2019/07/images-for-every-resolution/#fn1&quot; id=&quot;fnref1&quot;&gt;[1]&lt;/a&gt;&lt;/sup&gt; where it states, when we talk about pixels in CSS, we refer to a special unit.&lt;/p&gt;
&lt;p&gt;When we talk about &lt;code&gt;CSS px&lt;/code&gt;, we are not talking about &lt;em&gt;screen pixels&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;CSS px&lt;/code&gt; are defined to be small but visible, and in contrast to inches or cm, &lt;strong&gt;its size depends from where the user should see the screen&lt;/strong&gt;. So a CSS &lt;code&gt;1px&lt;/code&gt; in a phone will be smaller than a CSS &lt;code&gt;1px&lt;/code&gt; in a TV because the phone is a few centimeters from our face, but the TV can be a couple of meters away. Anyway, we should be able to see them in both places.&lt;/p&gt;
&lt;p&gt;CSS provides this unit, &lt;code&gt;CSS px&lt;/code&gt;, that allow us to work for all these different devices without having to worry on &lt;em&gt;how many screen pixels per inch my screen has&lt;/em&gt;. &lt;strong&gt;All that complexity is hidden behind CSS px&lt;/strong&gt;. And, of course, in the other CSS units that are &lt;code&gt;px&lt;/code&gt; based like &lt;code&gt;em&lt;/code&gt; and &lt;code&gt;rem&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;In my MacBook Pro screen, the relationship between &lt;em&gt;screen pixels&lt;/em&gt; and &lt;code&gt;CSS px&lt;/code&gt; is &lt;code&gt;2x&lt;/code&gt;. In order for images to look crisp, I need to provide a resource with the double of the size.&lt;/p&gt;
&lt;p&gt;But how do I knew the relationship between &lt;em&gt;screen pixels&lt;/em&gt; and &lt;code&gt;CSS px&lt;/code&gt;? Thankfully the browser exposes a property called &lt;code&gt;devicePixelRatio&lt;/code&gt;. I opened DevTools and I typed&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;window&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;devicePixelRatio &lt;span class=&quot;token comment&quot;&gt;// my result was &quot;2&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This result depends on the screen the browser is being used. If you happen to have another connected screen, this result may vary. Older desktop screens usually return &lt;code&gt;1&lt;/code&gt;. The newest phones are returning &lt;code&gt;3&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;how-many-images-should-i-provide&quot;&gt;How many images should I provide? &lt;a class=&quot;direct-link&quot; href=&quot;https://cmolina.dev/posts/2019/07/images-for-every-resolution/#how-many-images-should-i-provide&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This depends on the users of your website. If you need to support mobile device users with high-end phones, you should provide 3x, 2x and 1x versions of your assets.&lt;/p&gt;
&lt;h2 id=&quot;is-srcset-supported-by-browsers&quot;&gt;Is &amp;quot;srcset&amp;quot; supported by browsers? &lt;a class=&quot;direct-link&quot; href=&quot;https://cmolina.dev/posts/2019/07/images-for-every-resolution/#is-srcset-supported-by-browsers&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This is important. At the time of writing this article, support for &lt;code&gt;srcset&lt;/code&gt; attribute is pretty good &lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://cmolina.dev/posts/2019/07/images-for-every-resolution/#fn2&quot; id=&quot;fnref2&quot;&gt;[2]&lt;/a&gt;&lt;/sup&gt; —a good thing to notice is if we keep the &lt;code&gt;src&lt;/code&gt; attribute &lt;strong&gt;we will deliver an image to older browsers too&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;For this case, it makes sense to deliver the 1x URL in &lt;code&gt;src&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;In my example, the code for my icon looks like this&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;img&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token attr-name&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;icon-25.png&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token attr-name&quot;&gt;srcset&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;icon-25.png 1x, icon-50px 2x, icon-75.png 3x&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token attr-name&quot;&gt;alt&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion &lt;a class=&quot;direct-link&quot; href=&quot;https://cmolina.dev/posts/2019/07/images-for-every-resolution/#conclusion&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Summarizing,&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Know about your users and which devices they are using&lt;/li&gt;
&lt;li&gt;Define which resolutions you should provide: 1x, 2x and/or 3x&lt;/li&gt;
&lt;li&gt;Provides the assets they need by using &lt;code&gt;srcset&lt;/code&gt; attribute&lt;/li&gt;
&lt;li&gt;Deliver the experience for unsupported browsers by using &lt;code&gt;src&lt;/code&gt; attribute&lt;/li&gt;
&lt;li&gt;If it makes sense, remember to add an alternative text using &lt;code&gt;alt&lt;/code&gt; attribute&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That&#39;s all for now. Have a good day!&lt;/p&gt;
&lt;hr class=&quot;footnotes-sep&quot; /&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Bert Boss wrote an article for the W3C explaining the different units available in CSS, a bit of history, and which should we use depending on each situation &lt;a href=&quot;https://www.w3.org/Style/Examples/007/units.en.html&quot;&gt;https://www.w3.org/Style/Examples/007/units.en.html&lt;/a&gt; &lt;a href=&quot;https://cmolina.dev/posts/2019/07/images-for-every-resolution/#fnref1&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn2&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;&lt;code&gt;srcset&lt;/code&gt; worldwide support is over 90%. Anyway, you should understand who your users are, what devices are using, and provide what makes sense for your case &lt;a href=&quot;https://caniuse.com/#search=srcset&quot;&gt;https://caniuse.com/#search=srcset&lt;/a&gt; &lt;a href=&quot;https://cmolina.dev/posts/2019/07/images-for-every-resolution/#fnref2&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;

			
		</content>
	</entry>
	
	<entry>
		<title>Know your tools: JavaScript Promises</title>
		<link href="https://cmolina.dev/posts/2019/08/demistify-promises/"/>
		<updated>2019-08-07T00:00:00Z</updated>
		<id>https://cmolina.dev/posts/2019/08/demistify-promises/</id>
		<content type="html">
		  &lt;p&gt;I am sure you have used Promises before, but if you avoid them because of their mystical behavior, this article is for you.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;A Promise is an object that allows us to work on (possible) async task, and notify others when the task is done&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Initially, &lt;strong&gt;a Promise looks just like a glorified callback&lt;/strong&gt;. If you are familiar with NodeJS callbacks you&#39;ve seen this pattern before&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// callback version&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;asyncTask&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;error&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; result&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token function&quot;&gt;onError&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token function&quot;&gt;onSuccess&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;result&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If &lt;code&gt;asyncTask&lt;/code&gt; returns a Promise instead, this would be the equivalent version&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Promise version&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;asyncTask&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;onSuccess&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;catch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;onError&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The latest code present some advantages from the former:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;It is shorter: 3 vs 7 lines of code&lt;/li&gt;
&lt;li&gt;&lt;em&gt;onSuccess&lt;/em&gt; and &lt;em&gt;onError&lt;/em&gt; functions are going to be called at most once, and only one of them, &lt;strong&gt;guaranteed&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Promises are &lt;em&gt;microtasks&lt;/em&gt;, which means they run before functions from &lt;em&gt;macrotasks&lt;/em&gt; like &lt;code&gt;setTimeout&lt;/code&gt; or I/O&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;But one of the biggest benefits is for the &lt;em&gt;Developer Experience&lt;/em&gt;: running multiples async tasks without the callback hell.&lt;/p&gt;
&lt;h2 id=&quot;avoiding-callback-hell&quot;&gt;Avoiding callback hell &lt;a class=&quot;direct-link&quot; href=&quot;https://cmolina.dev/posts/2019/08/demistify-promises/#avoiding-callback-hell&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;What is the callback hell? Let&#39;s see an example by calling in series 4 async functions using callbacks&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// callback version&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;getCredentials&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;error&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; credentials&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;Credentials not found&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class=&quot;token function&quot;&gt;login&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;credentials&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;error&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; accessToken&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;Credentials are invalid&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;        &lt;span class=&quot;token function&quot;&gt;getHomeInformation&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;accessToken&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;error&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; homeInformation&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;There was an error getting your info&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;            &lt;span class=&quot;token function&quot;&gt;recordAnalytics&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;home loaded&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;                &lt;span class=&quot;token comment&quot;&gt;// we can keep adding indentation, forever... &lt;/span&gt;&lt;br /&gt;                &lt;span class=&quot;token comment&quot;&gt;// you will probably need a bigger monitor &lt;/span&gt;&lt;br /&gt;                &lt;span class=&quot;token comment&quot;&gt;// to avoid all the horizontal scrolling 😂&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Slowly, we start to increase indentation by each callback call — and we are not even properly handle errors!&lt;/p&gt;
&lt;p&gt;Let&#39;s take a look of how to handle this case with Promises&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Promises version&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;getCredentials&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;login&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;getHomeInformation&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;recordAnalytics&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;home loaded&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;catch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;/* Handles each error properly */&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The advantages are clear: keeping indentation under control. No need for buying a bigger monitor 😉&lt;/p&gt;
&lt;p&gt;Now, if you are used to use callbacks you can have the &lt;em&gt;Promise callback hell&lt;/em&gt; as well&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Promises + callback hell version&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// 🚫 DO NOT TRY THIS AT HOME! 🚫&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;getCredentials&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;credentials&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token function&quot;&gt;login&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;credentials&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;accessToken&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token function&quot;&gt;getHomeInformation&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;accessToken&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token function&quot;&gt;recordAnalytics&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;home loaded&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;                &lt;span class=&quot;token comment&quot;&gt;// for new async tasks, &lt;/span&gt;&lt;br /&gt;                &lt;span class=&quot;token comment&quot;&gt;// they will keep increasing indentation&lt;/span&gt;&lt;br /&gt;                &lt;span class=&quot;token comment&quot;&gt;// you will need to buy a new monitor, again 😂&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;catch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;There was an error getting your info&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;catch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;Credentials are invalid&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;catch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;Credentials not found&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Just by using Promises you don&#39;t avoid the callback hell: it is in your hands to use Promises as designed. Let&#39;s follow 3 simple rules that will help us improve our relationship with Promises.&lt;/p&gt;
&lt;h2 id=&quot;rule-1-on-success-and-on-error-should-always-return-or-throw&quot;&gt;Rule #1: &lt;code&gt;onSuccess&lt;/code&gt; and &lt;code&gt;onError&lt;/code&gt; should always return (or throw) &lt;a class=&quot;direct-link&quot; href=&quot;https://cmolina.dev/posts/2019/08/demistify-promises/#rule-1-on-success-and-on-error-should-always-return-or-throw&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Promise objects have two methods: &lt;code&gt;.then(onSuccess)&lt;/code&gt; and &lt;code&gt;.catch(onError)&lt;/code&gt;, and their received callback will be called when the Promise state changes from its initial value, &lt;em&gt;pending&lt;/em&gt;, to a &lt;em&gt;fulfilled&lt;/em&gt; or &lt;em&gt;rejected&lt;/em&gt; state respectively.&lt;/p&gt;
&lt;p&gt;For both &lt;code&gt;onSuccess&lt;/code&gt; and &lt;code&gt;onError&lt;/code&gt; callbacks it is a good practice to always &lt;code&gt;return&lt;/code&gt; (or to &lt;code&gt;throw&lt;/code&gt;), to pass a value to the next chained &lt;code&gt;.then/.catch&lt;/code&gt;. But what should we return?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;a sync value (a number, an object, a string...), or&lt;/li&gt;
&lt;li&gt;another Promise object&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In case of a Promise, its result &lt;strong&gt;will be the value available for the next chained &lt;code&gt;.then/.catch&lt;/code&gt;&lt;/strong&gt;. Let&#39;s look at some examples&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// always return/throw&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;fetch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;https://api.domain.com/&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; response&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;  &lt;span class=&quot;token comment&quot;&gt;// pass its result to the next `.then`&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;id&#39;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; json&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; json&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;         &lt;span class=&quot;token comment&quot;&gt;// pass the object to the next `.then`&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;// skip all following `.then` and pass error to next `.catch`&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;id is not present&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;validatedJson&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;// we have an object with an `id`&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And what happen if we don&#39;t return nor throw? Promises will not be chained at things will run in an order not guaranteed. Look at these anti-patterns&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// random things you can do inside a `.then`&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// 🚫 DO NOT TRY THIS AT HOME! 🚫&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;fetch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;https://api.domain.com/&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;response&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    response&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;    &lt;span class=&quot;token comment&quot;&gt;// 🐛 function doesn&#39;t return, order isn&#39;t guaranteed!&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;json&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;  &lt;span class=&quot;token comment&quot;&gt;// 🐛 received undefined from last `.then`, not what we expected!&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;                &lt;span class=&quot;token comment&quot;&gt;// 🐛 no function at all, resolved value will pass to next `then`&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;aPromiseObject&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;  &lt;span class=&quot;token comment&quot;&gt;// 🐛 expected a function, received an object!&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;rule-2-prepare-for-errors-always-catch&quot;&gt;Rule #2: Prepare for errors, always &lt;code&gt;catch&lt;/code&gt; &lt;a class=&quot;direct-link&quot; href=&quot;https://cmolina.dev/posts/2019/08/demistify-promises/#rule-2-prepare-for-errors-always-catch&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This rule is simple. Eventually, things will go wrong and you have to prepare for that case.&lt;/p&gt;
&lt;p&gt;Always place a &lt;code&gt;.catch&lt;/code&gt; at the end of your Promise chains and make sure you handle unexpected errors. If you don&#39;t, modern browsers will print an error in the console: that is really useful for you during development but gives users no clue if they press a button and nothing happens.&lt;/p&gt;
&lt;p&gt;Continuing with the previous example,&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// always catch&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;fetch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;https://api.domain.com/&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; response&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;id&#39;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; json&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; json&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;id is not present&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;catch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;message &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;id is not present&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token comment&quot;&gt;// handle the `id` was not present error&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token comment&quot;&gt;// other errors, like fetch failing&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Remember: think in your users and always add &lt;em&gt;at least one&lt;/em&gt; &lt;code&gt;.catch&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;rule-3-create-promise-with-the-right-approach&quot;&gt;Rule #3: Create Promise with the right approach &lt;a class=&quot;direct-link&quot; href=&quot;https://cmolina.dev/posts/2019/08/demistify-promises/#rule-3-create-promise-with-the-right-approach&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Until this moment, Promise objects have appeared from existing APIs. But how can we create our own Promises?&lt;/p&gt;
&lt;h3 id=&quot;create-a-promise-from-a-sync-value&quot;&gt;Create a Promise from a sync value &lt;a class=&quot;direct-link&quot; href=&quot;https://cmolina.dev/posts/2019/08/demistify-promises/#create-a-promise-from-a-sync-value&quot;&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;This is easy: all you have to do is call &lt;code&gt;Promise.resolve(value)&lt;/code&gt; or &lt;code&gt;Promise.reject(message)&lt;/code&gt; if you want a fulfilled or rejected Promise.&lt;/p&gt;
&lt;h3 id=&quot;create-a-promise-from-a-callback&quot;&gt;Create a Promise from a callback &lt;a class=&quot;direct-link&quot; href=&quot;https://cmolina.dev/posts/2019/08/demistify-promises/#create-a-promise-from-a-callback&quot;&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;If you want to convert a callback-based function to return a Promise you will have to call the Promise constructor. Let&#39;s look an example:&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// from NodeJS callback to Promise&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;asyncTaskPromise&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;resolve&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; reject&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token function&quot;&gt;asyncTask&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;error&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; result&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;reject&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;resolve&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;result&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;asyncTaskPromise&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now that you know the basic rules, let&#39;s take a look to a bit more advanced patterns you will be writing.&lt;/p&gt;
&lt;h2 id=&quot;advanced-promise-patterns&quot;&gt;Advanced Promise patterns &lt;a class=&quot;direct-link&quot; href=&quot;https://cmolina.dev/posts/2019/08/demistify-promises/#advanced-promise-patterns&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;You have to be mindful and create Promise &lt;em&gt;only when you need them&lt;/em&gt;. Consider this: you have a dynamic list of Promises you want to run in parallel, and other list to be run in series each after other. How would you approach each case?&lt;/p&gt;
&lt;h3 id=&quot;running-in-parallel&quot;&gt;Running in parallel &lt;a class=&quot;direct-link&quot; href=&quot;https://cmolina.dev/posts/2019/08/demistify-promises/#running-in-parallel&quot;&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Use &lt;code&gt;Promise.all(list)&lt;/code&gt; to wait for a list of promises to be ready. If every Promise succeeded you will receive a list with their corresponding values in the next &lt;code&gt;.then&lt;/code&gt;; if any of them fails you will get the error in the next &lt;code&gt;.catch&lt;/code&gt;.&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// running in parallel ✈️️️️️️️️️️ ✈️️️️️️️️️️️️ ✈️️️️️️️️️️️️ ✈️️️️️️️️️️️️&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; urls &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;/1&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;/2&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;/3&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;/4&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// fetch are triggered &quot;in parallel&quot;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; promises &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; urls&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;url&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fetch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;url&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Promise&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;all&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;promises&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;responses&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; responses&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;res&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; res&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;jsons&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;// we have an array with the json for each call!&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;catch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;// the first rejected error will get here&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;running-in-series&quot;&gt;Running in series &lt;a class=&quot;direct-link&quot; href=&quot;https://cmolina.dev/posts/2019/08/demistify-promises/#running-in-series&quot;&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;What if we need to wait for the result of a previous Promise before calling the next one?&lt;/p&gt;
&lt;p&gt;Running a &lt;code&gt;.map&lt;/code&gt; will not work as the Promise is created in that moment. You need to create a function that will return a new Promise when needed (also called a &lt;em&gt;factory&lt;/em&gt;).&lt;/p&gt;
&lt;p&gt;Start the Promise series with an initial &lt;code&gt;Promise.resolve()&lt;/code&gt;, just to have something where to chain to (call &lt;code&gt;.then&lt;/code&gt;).&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// run in series 🚂🚃🚃🚃&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; series &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Promise&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;resolve&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;urls&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;forEach&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;url&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    series&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;previousText&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fetchFactory&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;url&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; previousText&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;series&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;finalText&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;// we have the last Promise result&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;catch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;// the first rejected error will get here&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fetchFactory&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;url&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; text&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;text&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        url &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; url &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;?text=&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; text&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fetch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;url&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;response&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; response&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;cancelling-a-promise&quot;&gt;Cancelling a Promise &lt;a class=&quot;direct-link&quot; href=&quot;https://cmolina.dev/posts/2019/08/demistify-promises/#cancelling-a-promise&quot;&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Let&#39;s say you want to poll an API, and you want to have a way to cancel it. There is no &lt;code&gt;.cancel&lt;/code&gt; method in the Promise class, but we can achieve something similar by creating our own &lt;code&gt;cancel&lt;/code&gt; function by racing between Promises.&lt;/p&gt;
&lt;p&gt;Here I used &lt;code&gt;Promise.race(list)&lt;/code&gt;: it receives a list of Promises and resolves or rejects as soon as one of the Promise from its list resolves or rejects, with the value from that Promise.&lt;/p&gt;
&lt;p&gt;In the next example, a &lt;code&gt;wait&lt;/code&gt; Promise will race against the user cancelling the Promise. If the user never cancels, the system will keep polling until the response has a &lt;code&gt;status === &#39;ready&#39;&lt;/code&gt; and will fulfilled with the json response. If the user cancel, the Promise will reject with a message &lt;code&gt;&#39;cancelled by user&#39;&lt;/code&gt; instead.&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;wait&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;delay&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;resolve&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;setTimeout&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;resolve&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; delay&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;cancellablePolling&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;url&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; ms&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; rejectCallback&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; cancelPromise &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;resolve&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; reject&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        rejectCallback &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; reject&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;poll&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; Promise&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;race&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;wait&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ms&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; cancelPromise&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fetch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;url&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; response&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; json&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;status &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;ready&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; json &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;poll&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;cancel&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;rejectCallback&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;cancelled by user&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; promise &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;poll&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        cancel&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;        promise&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; promise&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; cancel &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;cancellablePolling&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;/status&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5000&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;promise&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;      &lt;span class=&quot;token comment&quot;&gt;// is a regular Promise&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;cancel&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;               &lt;span class=&quot;token comment&quot;&gt;// that will be rejected if `cancel` is called before &lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;what-s-next&quot;&gt;What&#39;s next? &lt;a class=&quot;direct-link&quot; href=&quot;https://cmolina.dev/posts/2019/08/demistify-promises/#what-s-next&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Once you feel comfortable with Promises, a nice addition to the JavaScript language is the &lt;code&gt;await&lt;/code&gt; operator and the &lt;code&gt;async&lt;/code&gt; functions. This allows to call async functions in a more standard syntax, like sync functions with the regular &lt;code&gt;try/catch&lt;/code&gt; statements.&lt;/p&gt;
&lt;p&gt;By using &lt;code&gt;async function&lt;/code&gt; you declare a function to be async, and always returning a Promise. The advantage is now you can &amp;quot;halt&amp;quot; the execution of your function and &lt;code&gt;wait&lt;/code&gt; for Promises to fulfill. Let&#39;s take a look to the first example of this article and see how it is different:&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// callback version&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;main&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token function&quot;&gt;asyncTask&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;error&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; result&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token function&quot;&gt;onError&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token function&quot;&gt;onSuccess&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;result&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and now, using &lt;code&gt;async function + await&lt;/code&gt;, assuming &lt;code&gt;asyncTaskPromise&lt;/code&gt; is the Promise version of &lt;code&gt;asyncTask&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Promise version, async function/await&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;main&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;asyncTaskPromise&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token function&quot;&gt;onSuccess&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;result&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token function&quot;&gt;onError&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Currently, &lt;code&gt;Promises&lt;/code&gt; are &lt;a href=&quot;https://caniuse.com/#feat=promises&quot;&gt;widely supported&lt;/a&gt; across browsers &lt;a href=&quot;https://caniuse.com/#feat=async-functions&quot;&gt;as well as&lt;/a&gt; &lt;code&gt;async functions&lt;/code&gt;, both over 90%. The recommendation is to understand who are your users and polyfill and/or transpile if it makes sense.&lt;/p&gt;
&lt;p&gt;Hope you have learn something today. Do you have your own rules or advances uses cases for Promises? Comment them below. Have a nice week!&lt;/p&gt;

			
		</content>
	</entry>
	
	<entry>
		<title>Small Things Matter: Returning early</title>
		<link href="https://cmolina.dev/posts/2020/01/return-early/"/>
		<updated>2020-01-16T00:00:00Z</updated>
		<id>https://cmolina.dev/posts/2020/01/return-early/</id>
		<content type="html">
		  &lt;p&gt;At the begging of my career as software developer I remember writing really long functions, full of nested conditionals.&lt;/p&gt;
&lt;p&gt;I asked a teacher what could you do about this, and this was the first time I was introduced to the &amp;quot;return early&amp;quot; pattern, which improved the readability of my code by a great extent.&lt;/p&gt;
&lt;h2 id=&quot;the-rule&quot;&gt;The rule &lt;a class=&quot;direct-link&quot; href=&quot;https://cmolina.dev/posts/2020/01/return-early/#the-rule&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Every time when you are faced with a conditional in a function:&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;condition&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token function&quot;&gt;doA&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token function&quot;&gt;doB&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;it is possible to rewrite it in a way you &lt;strong&gt;return&lt;/strong&gt; after the condition, making the else block redundant.&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;condition&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;        &lt;span class=&quot;token function&quot;&gt;doA&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;mark class=&quot;highlight-line highlight-line-active&quot;&gt;        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/mark&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;mark class=&quot;highlight-line highlight-line-active&quot;&gt;    &lt;span class=&quot;token comment&quot;&gt;// look mam, no else!&lt;/span&gt;&lt;/mark&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token function&quot;&gt;doB&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This effectively allows you to:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;write code with less indentation (i.e. less horizontal scrolling)&lt;/li&gt;
&lt;li&gt;reduce cognitive load, as when you return you don&#39;t need to keep in mind what happen in the other branch of the condition&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;the-example&quot;&gt;The example &lt;a class=&quot;direct-link&quot; href=&quot;https://cmolina.dev/posts/2020/01/return-early/#the-example&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;So this seems like a small change that may not have a lot of sense. However, when small improvements are put in place together, the change is noticeable.&lt;/p&gt;
&lt;p&gt;Let&#39;s take a look of a function in charge of handling an HTTP request for getting scheduled classes of a gym&#39;s customer:&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getScheduledClasses&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;req&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; res&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;req&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;req&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;hasPaidMembership&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; classes &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getScheduledClassesForUser&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;classes&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;                &lt;span class=&quot;token function&quot;&gt;res&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;200&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; classes &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;                &lt;span class=&quot;token function&quot;&gt;res&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;204&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// No content&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token function&quot;&gt;res&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;403&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; reason&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;not_paid_membership&#39;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token function&quot;&gt;res&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;401&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Unauthorized&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;By swapping the conditional to &lt;strong&gt;always return early the logic with less processing&lt;/strong&gt;, we can rewrite this as follow:&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getScheduledClasses&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;req&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; res&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;req&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;res&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;401&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;req&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;hasPaidMembership&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;res&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;403&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; reason&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;not_paid_membership&#39;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; classes &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getScheduledClassesForUser&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;classes&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;res&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;204&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// No content&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class=&quot;token function&quot;&gt;res&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;200&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; classes &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This code presents less indentation, which improves readability. In the first snippet, indentation is correlated to conditionals; in the latest, conditions are presented in a procedural way.&lt;/p&gt;
&lt;p&gt;Notice that both snippets have the same amount of lines, however the second one has way more new lines to separate the intention of each block.&lt;/p&gt;
&lt;p&gt;What do you think of the technique? Have you used before? Do you think it may make sense applied to your codebase?&lt;/p&gt;

			
		</content>
	</entry>
	
	<entry>
		<title>Retrying functions in JavaScript</title>
		<link href="https://cmolina.dev/posts/2020/02/retrying-functions/"/>
		<updated>2020-02-20T00:00:00Z</updated>
		<id>https://cmolina.dev/posts/2020/02/retrying-functions/</id>
		<content type="html">
		  &lt;p&gt;The problem statement is: you want to execute a function that may fail, and you want to retry it N times. How could you solve this?&lt;/p&gt;
&lt;p&gt;An initial approach can be to program it for a specific number of times. Let&#39;s run &lt;code&gt;functionThatMayFail&lt;/code&gt; and retry it 3 times&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token function&quot;&gt;functionThatMayFail&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;e0&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token comment&quot;&gt;// 1st retry&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token function&quot;&gt;functionThatMayFail&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;e1&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token comment&quot;&gt;// 2nd retry&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token function&quot;&gt;functionThatMayFail&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;e2&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;                &lt;span class=&quot;token comment&quot;&gt;// 3rd retry&lt;/span&gt;&lt;br /&gt;                &lt;span class=&quot;token function&quot;&gt;functionThatMayFail&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;e3&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;                &lt;span class=&quot;token comment&quot;&gt;// give up&lt;/span&gt;&lt;br /&gt;                &lt;span class=&quot;token function&quot;&gt;handleException&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;e3&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The previous snippet has some problems:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;it involves duplication, and&lt;/li&gt;
&lt;li&gt;the number of retries can&#39;t be modified at runtime&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;By using recursion we could write a second approach that may address those disadvantages —however I would advocate to avoid it if possible, as this is not a recursive problem &lt;em&gt;per se&lt;/em&gt; and the code will be harder to read and debug.&lt;/p&gt;
&lt;p&gt;A third approach I&#39;m more willing to follow is to make a utility function that takes care of both &lt;em&gt;calling a function and its retries&lt;/em&gt;,&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;callAndRetry&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;fn&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; maxAmountOfRetries&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; error&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; retries &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; retries &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; maxAmountOfRetries&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; retries&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;            error &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; err&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; error&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In our example, this should be used as&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token function&quot;&gt;callAndRetry&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;functionThatMayFail&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token function&quot;&gt;handleException&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The presented approach solves the original statement and doesn&#39;t have the disadvantages of the previous methods. Another good thing about this pattern is that can be repurposed for asynchronous functions as well. How so?&lt;/p&gt;
&lt;p&gt;Let&#39;s say &lt;code&gt;functionThatMayFail&lt;/code&gt; now returns a Promise. Instead of hard-coding retries or going recursive, we can &lt;em&gt;slightly&lt;/em&gt; modify &lt;code&gt;callAndRetry&lt;/code&gt; to wait for the function to fulfill, as&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;mark class=&quot;highlight-line highlight-line-active&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;callAndRetry&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;fn&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; maxAmountOfRetries&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/mark&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; error&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; retries &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; retries &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; maxAmountOfRetries&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; retries&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;        &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;mark class=&quot;highlight-line highlight-line-active&quot;&gt;            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/mark&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;            error &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; err&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; error&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Did you notice how we now use an &lt;a href=&quot;https://wiki.developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function&quot;&gt;async function&lt;/a&gt; and &lt;code&gt;await&lt;/code&gt; for the &lt;code&gt;fn&lt;/code&gt; function to fulfill? All the rest remains unchanged.&lt;/p&gt;
&lt;p&gt;This new version can be used with the typical Promise chaining,&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token function&quot;&gt;callAndRetry&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;functionThatMayFail&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;catch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;handleException&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But I believe there is even more value when it is used like a sync call:&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// in the context of an async function, so we can `await`&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;callAndRetry&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;functionThatMayFail&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token function&quot;&gt;handleException&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And the reasons are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;we use regular &lt;code&gt;try/catch&lt;/code&gt; for error exception, and&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;this code can be used for both synchronous and asynchronous functions!&lt;/strong&gt; Yes, &lt;code&gt;functionThatMayFail&lt;/code&gt; may return a Promise or anything else and this would still works.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Another advantage of using a snippet to encapsulate the retry logic, instead of mixing it with the business logic, is that we can write it once and reused in your whole project as needed. You may even install one its versions available at &lt;a href=&quot;https://www.npmjs.com/search?q=retry&quot;&gt;NPM&lt;/a&gt; which include different retry strategies, if you need them.&lt;/p&gt;
&lt;p&gt;I read your feedback in the comments below. Happy retrying!&lt;/p&gt;

			
		</content>
	</entry>
	
	<entry>
		<title>Logging functions in JavaScript</title>
		<link href="https://cmolina.dev/posts/2020/05/logging-functions/"/>
		<updated>2020-05-18T00:00:00Z</updated>
		<id>https://cmolina.dev/posts/2020/05/logging-functions/</id>
		<content type="html">
		  &lt;p&gt;Logs can be very useful to debug issues in production environments.&lt;/p&gt;
&lt;p&gt;By logging when functions are called, with which parameters, it is possible to reproduce issues and find root causes.&lt;/p&gt;
&lt;p&gt;I will explore the logging of functions and methods within classes.&lt;/p&gt;
&lt;h2 id=&quot;functions&quot;&gt;Functions &lt;a class=&quot;direct-link&quot; href=&quot;https://cmolina.dev/posts/2020/05/logging-functions/#functions&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Let&#39;s say we have a function we&#39;d like to know when it is being called, its parameters, and its result.&lt;/p&gt;
&lt;p&gt;In this example, the function is called &lt;code&gt;range()&lt;/code&gt; that when given two numbers it returns a list with the digits between them, excluding the last:&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;start&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; end&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;Array&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;end &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; start&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;fill&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;start&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;start&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; index&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; start &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; index&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;    &lt;span class=&quot;token comment&quot;&gt;// returns [0, 1, 2, 3, 4]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;An initial approach would be to edit the original function and add the logs needed:&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;start&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; end&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;mark class=&quot;highlight-line highlight-line-active&quot;&gt;    console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;Calling range(&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;start&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;end&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/mark&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;Array&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;end &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; start&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;        &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;fill&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;start&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;        &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;start&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; index&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; start &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; index&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;&lt;br /&gt;&lt;mark class=&quot;highlight-line highlight-line-active&quot;&gt;    console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;range(&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;start&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;end&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;) returns &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;result&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/mark&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; result&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token function&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;    &lt;span class=&quot;token comment&quot;&gt;// returns [0, 1, 2, 3, 4]&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// logs these two lines&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;//    Calling range(0, 5)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;//    range(0, 5) returns 0,1,2,3,4&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This works, however it makes the function harder to read by mixing the proper logic of the function and the boilerplate to make the logs. This may be okay for a 3 line function, however longer ones will become even longer and harder, making them harder to read and to make changes.&lt;/p&gt;
&lt;p&gt;An alternative solution would be to move all the logging logic outside to its function:&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// let&#39;s keep the original version of `range()` without logging statements&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// `logFunction()` creates a new function that handles the logging for us&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;mark class=&quot;highlight-line highlight-line-active&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;logFunction&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;fn&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; thisArg&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/mark&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;        &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; concatenatedArguments &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Array&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;arguments&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;, &#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;        console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;Calling &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;fn&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;concatenatedArguments&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;        &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;apply&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;thisArg&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; arguments&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;        console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;fn&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;concatenatedArguments&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;) returns &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;result&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; result&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// create a version of `range()` with logs&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;mark class=&quot;highlight-line highlight-line-active&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; loggedRange &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;logFunction&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;range&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/mark&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token function&quot;&gt;loggedRange&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;    &lt;span class=&quot;token comment&quot;&gt;// returns [0, 1, 2, 3, 4]&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// logs these two lines&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;//    Calling range(0, 5)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;//    range(0, 5) returns 0,1,2,3,4&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;There are advantages to this approach:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;now the business logic doesn&#39;t need to be mixed with logging, keeping our functions shorter,&lt;/li&gt;
&lt;li&gt;you can reuse this function into other functions that need logging as well&lt;/li&gt;
&lt;li&gt;if you don&#39;t need the logs anymore, stop calling &lt;code&gt;logFunction&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Sweet. What about methods?&lt;/p&gt;
&lt;h2 id=&quot;methods-within-classes&quot;&gt;Methods within classes &lt;a class=&quot;direct-link&quot; href=&quot;https://cmolina.dev/posts/2020/05/logging-functions/#methods-within-classes&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Let&#39;s take the example of a &lt;code&gt;LoginEmailService&lt;/code&gt; class, that needs logging for its 2 methods:&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;LoginEmailService&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token function&quot;&gt;lostPasswordFor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;emailAddress&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; usersDB&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token function&quot;&gt;verifyEmailAddressFor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;user&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; emailAddress&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Following the idea of keeping logic apart from the logs, we can &lt;strong&gt;create a new class&lt;/strong&gt; that extends the original one and makes the logging for us. A first attempt would be:&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;LoggedLoginEmailService&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;LoginEmailService&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token comment&quot;&gt;// option 1: placing the logs directly&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token function&quot;&gt;lostPasswordFor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;emailAddress&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; usersDB&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;mark class=&quot;highlight-line highlight-line-active&quot;&gt;        console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;Calling lostPasswordFor(&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;emailAddress&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;usersDB&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/mark&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;        &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;lostPasswordFor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;emailAddress&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; usersDB&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;mark class=&quot;highlight-line highlight-line-active&quot;&gt;        console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;lostPasswordFor(&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;emailAddress&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;usersDB&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;) returns &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;result&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/mark&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; result&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token comment&quot;&gt;// option 2: using `logFunction()`&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token function&quot;&gt;verifyEmailAddressFor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;mark class=&quot;highlight-line highlight-line-active&quot;&gt;        &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; loggedVerifyEmailAddressFor &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;logFunction&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;verifyEmailAddressFor&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/mark&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;loggedVerifyEmailAddressFor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;apply&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; arguments&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In the example, it works fine to place the logs directly or reusing the &lt;code&gt;logFunction()&lt;/code&gt; utility. However, neither of those options will scale well when adding more methods to the original class as it will require manual updates within &lt;code&gt;LoggedLoginEmailService&lt;/code&gt; class.&lt;/p&gt;
&lt;p&gt;Wouldn&#39;t it be nice if logs are added to all methods of a class, including future modifications? This is possible using the &lt;code&gt;Proxy&lt;/code&gt; class, used to define custom behavior for operations like reading a property and function invocation. If you want to know more about Proxy &lt;a href=&quot;https://javascript.info/proxy&quot;&gt;read this excellent article&lt;/a&gt;. Go on and read it, I&#39;ll wait here.&lt;/p&gt;
&lt;p&gt;For the next example we will write 2 functions using Proxies:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;an external one, &lt;code&gt;loggingMethodsFor()&lt;/code&gt;, will listen for reading the properties of an object, and will invoke...&lt;/li&gt;
&lt;li&gt;the internal &lt;code&gt;logMethod()&lt;/code&gt; to log when a method is executed&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;mark class=&quot;highlight-line highlight-line-active&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; loggedLoginEmailService &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;loggingMethodsFor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;LoginEmailService&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/mark&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;loggedLoginEmailService&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;lostPasswordFor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;a@b.c&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;db&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// log these two lines:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;//    Calling LoginEmailService.lostPasswordFor(a@b.c,dbObject)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;//    LoginEmailService.lostPasswordFor(a@b.c, db) returns &amp;lt;...&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;&lt;br /&gt;&lt;mark class=&quot;highlight-line highlight-line-active&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;loggingMethodsFor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;instance&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/mark&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Proxy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;instance&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;        &lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;target&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; propertyName&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;            &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; property &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; target&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;propertyName&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;            &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isMethod&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;property&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;                &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;logMethod&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;property&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; target&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;constructor&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; property&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;isMethod&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;property&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;typeof&lt;/span&gt; property &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;function&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// equivalent of `logFunction()` but for methods&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;mark class=&quot;highlight-line highlight-line-active&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;logMethod&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;method&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; className&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/mark&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Proxy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;method&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;        &lt;span class=&quot;token function&quot;&gt;apply&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;fn&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; thisArg&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; argumentsList&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;            &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; concatenatedArguments &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Array&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;argumentsList&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;, &#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;            console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;Calling &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;className&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;fn&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;concatenatedArguments&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;            &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;apply&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;thisArg&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; argumentsList&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;            console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;className&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;fn&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;concatenatedArguments&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;) returns &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;result&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; result&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Do you realize how similar both &lt;code&gt;logFunction()&lt;/code&gt; and &lt;code&gt;logMethod()&lt;/code&gt; are? By using the fact that there are no technical differences between methods and functions, we can modify &lt;code&gt;logFunction()&lt;/code&gt; for logging &lt;em&gt;both methods and functions&lt;/em&gt;.&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;logFunction&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;methodOrFn&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; className&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; isMethod &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; className &lt;span class=&quot;token operator&quot;&gt;!==&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;undefined&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Proxy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;methodOrFn&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token function&quot;&gt;apply&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;fn&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; thisArg&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; argumentsList&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; concatenatedArguments &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Array&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;argumentsList&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;, &#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; fnPrefix &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; isMethod &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; className &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;.&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;            console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;Calling &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;fnPrefix&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;fn&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;concatenatedArguments&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;            &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;apply&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;thisArg&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; argumentsList&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;            console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;fnPrefix&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;fn&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;concatenatedArguments&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;) returns &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;result&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; result&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;what-about-promises&quot;&gt;What about Promises? &lt;a class=&quot;direct-link&quot; href=&quot;https://cmolina.dev/posts/2020/05/logging-functions/#what-about-promises&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;You may be wondering what if the function or method returns a Promise. Currently, this function is printing &lt;code&gt;&amp;quot;[object Promise]&amp;quot;&lt;/code&gt; which is not helpful at all. Let&#39;s modify the latest lines of &lt;code&gt;logFunction()&lt;/code&gt; to change the way the output is logged.&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// inside `logFunction()`&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// …&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;apply&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;thisArg&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; argumentsList&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; returnsPromise &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; result &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;then &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;typeof&lt;/span&gt; result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;then &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;function&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;returnsPromise&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;output&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;fnToString&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt; returns &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;output&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;fnPrefix&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;fn&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;concatenatedArguments&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;) returns &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;result&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; result&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// …&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion &lt;a class=&quot;direct-link&quot; href=&quot;https://cmolina.dev/posts/2020/05/logging-functions/#conclusion&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;We explored how functions and methods can log their arguments and output without mixing log statements with the business logic.&lt;/p&gt;
&lt;p&gt;We reach to a single function that can be used for both functions and methods, handling Promises and non-Promises outputs.&lt;/p&gt;
&lt;p&gt;Even if our &lt;code&gt;logFunction()&lt;/code&gt; and &lt;code&gt;loggingMethodsFor()&lt;/code&gt; functions work they may not be ready for production. For example, depending on how complex are the arguments received by your functions you may want to deep dive into how the &lt;code&gt;concatenatedArguments&lt;/code&gt; variable is being built, by leveraging &lt;code&gt;JSON.stringify&lt;/code&gt; or any other technique to convert variables to a string. You may also need to avoid logging every method within an object, by having a blocked or allowed list of methods.&lt;/p&gt;
&lt;p&gt;I will write here the latest version of the two functions in case you want to play with them. Also split some logic into smaller functions to make it easier to read.&lt;/p&gt;
&lt;p&gt;Do you have other ideas for logging?&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;loggingMethodsFor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;instance&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Proxy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;instance&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;target&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; propertyName&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; property &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; target&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;propertyName&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;            &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;typeof&lt;/span&gt; property &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;function&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;                &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;logFunction&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;property&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; target&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;constructor&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; property&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;logFunction&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;methodOrFn&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; className&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Proxy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;methodOrFn&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token function&quot;&gt;apply&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;fn&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; thisArg&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; argumentsList&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; fnToString &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;functionAndArgumentsToString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;argumentsList&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; className&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; fn&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token function&quot;&gt;logFunctionStarts&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;fnToString&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;apply&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;thisArg&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; argumentsList&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token function&quot;&gt;logFunctionEnds&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;fnToString&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; result&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; result&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;functionAndArgumentsToString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;argumentsList&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; className&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; functionName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; concatenatedArguments &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Array&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;argumentsList&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;, &#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; functionPrefix &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; className &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; className &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;.&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;functionPrefix&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;functionName&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;concatenatedArguments&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;logFunctionStarts&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;fnToString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;Calling &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;fnToString&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;logFunctionEnds&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;fnToString&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; result&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; isPromise &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; result &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;then &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;typeof&lt;/span&gt; result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;then &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;function&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;isPromise&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;output&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;fnToString&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt; returns &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;output&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;fnToString&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt; returns &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;result&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

			
		</content>
	</entry>
	
	<entry>
		<title>Time-out functions in JavaScript</title>
		<link href="https://cmolina.dev/posts/2020/06/timeout-functions/"/>
		<updated>2020-06-14T00:00:00Z</updated>
		<id>https://cmolina.dev/posts/2020/06/timeout-functions/</id>
		<content type="html">
		  &lt;p&gt;I&#39;ve been thinking about the problem of &lt;em&gt;time-out a function&lt;/em&gt;, this is, try to run a function until a maximum amount of time, so it can either complete in time or be interrupted.&lt;/p&gt;
&lt;p&gt;So I rolled up my sleeves and wrote this&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;runWithTimeout&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;fn&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; timeoutInMs&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; timeoutId&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; timeout &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;resolve&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; reject&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        timeoutId &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;setTimeout&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;reject&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;timeout&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; timeoutInMs&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; fnResult &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Promise&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;resolve&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Promise&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;race&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;fnResult&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; timeout&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;finally&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;clearTimeout&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;timeoutId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It is meant to be used by passing a function with no parameters, plus how many milliseconds should be allowed to run. And by wrapping it in a Promise it can support both synchronous and asynchronous values.&lt;/p&gt;
&lt;p&gt;However, &lt;code&gt;runWithTimeout()&lt;/code&gt; doesn&#39;t work as expected.&lt;/p&gt;
&lt;p&gt;The rest of the article I&#39;ll explain why this function doesn&#39;t work and why it is impossible to solve this problem in JavaScript.&lt;/p&gt;
&lt;p&gt;Consider these examples,&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;uninterruptibleFaultySync&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;uninterruptibleFaultyAsync&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;queueMicrotask&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;uninterruptibleFaultyAsync&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;both will never be interrupted by the &lt;code&gt;runWithTimeout()&lt;/code&gt; function. How so?&lt;/p&gt;
&lt;h2 id=&quot;java-script-is-a-single-threaded-language&quot;&gt;JavaScript is a single-threaded language &lt;a class=&quot;direct-link&quot; href=&quot;https://cmolina.dev/posts/2020/06/timeout-functions/#java-script-is-a-single-threaded-language&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;If JavaScript is a single-threaded language, this means a single function is being executed at any given point in time. But then how do we have asynchronous functions? The answer is in the &lt;strong&gt;event loop&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;The event loop is a list of functions that the JavaScript engine will be running, in order. If there are no functions in the event loop, the engine will be doing nothing until a new function is placed on the list.&lt;/p&gt;
&lt;p&gt;The functions in the event loop are called &lt;strong&gt;tasks&lt;/strong&gt; or &lt;strong&gt;macrotasks&lt;/strong&gt;. How are tasks created? Functions run when a file is loaded, and functions placed with &lt;code&gt;setTimeout()&lt;/code&gt;, &lt;code&gt;setInterval()&lt;/code&gt; are the most common examples.&lt;/p&gt;
&lt;p&gt;The interesting thing about macrotasks is, once a task starts running it will run until completion with no interruptions. That&#39;s the reason why &lt;code&gt;uninterruptibleFaultySync()&lt;/code&gt;, which never ends, will run forever. But for other functions that do complete, they allow the event loop to execute the next function in its queue.&lt;/p&gt;
&lt;p&gt;This is not the whole story. There are other types of functions that are considered by the event loop which have more priority than the macrotasks: they are called &lt;strong&gt;microtasks&lt;/strong&gt;. Microtasks are run when the current macrotask completes, and the next macrotask will not be taken until the list of microtasks is empty. How are microtasks created? With Promises and calls to &lt;code&gt;queueMicrotask()&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;And because microtasks functions will be run until completion with no interruptions, calling &lt;code&gt;uninterruptibleFaultyAsync()&lt;/code&gt; will keep putting elements in the microtask list, never allowing pending macrotasks to be started. But for other microtasks that do complete, without creating infinite microtasks, they allow the event loop to keep running the macrotasks in its queue.&lt;/p&gt;
&lt;h2 id=&quot;is-there-a-way-to-timeout-a-function&quot;&gt;Is there a way to timeout a function? &lt;a class=&quot;direct-link&quot; href=&quot;https://cmolina.dev/posts/2020/06/timeout-functions/#is-there-a-way-to-timeout-a-function&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I am afraid it is not possible, at least for the general case. You can see this &lt;a href=&quot;https://stackoverflow.com/questions/8778718/how-to-implement-a-function-timeout-in-javascript-not-just-the-settimeout&quot;&gt;related question in Stack Overflow&lt;/a&gt; to read other people answers.&lt;/p&gt;
&lt;p&gt;Now, if the function you want to timeout is not a buggy one, like the uninterruptible ones presented here, &lt;code&gt;runWithTimeout()&lt;/code&gt; will indeed help you trigger a timeout error if necessary.&lt;/p&gt;
&lt;p&gt;How can you avoid writing uninterruptible functions? Here I bring some ideas:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;always return a Promise&lt;/li&gt;
&lt;li&gt;ensure your Promises are catching errors&lt;/li&gt;
&lt;li&gt;ensure, for loops and recursion, that the function will stop&lt;/li&gt;
&lt;/ul&gt;

			
		</content>
	</entry>
	
	<entry>
		<title>Publish a TypeScript package in npm</title>
		<link href="https://cmolina.dev/posts/2020/07/publish-typescript-package/"/>
		<updated>2020-07-11T00:00:00Z</updated>
		<id>https://cmolina.dev/posts/2020/07/publish-typescript-package/</id>
		<content type="html">
		  &lt;p&gt;Would you like to reuse that fancy function from a previous project? I do. All the time. And what I always do is to copy and paste it, and call it a day. But… wouldn&#39;t it be nice to &lt;em&gt;import&lt;/em&gt; the function?&lt;/p&gt;
&lt;p&gt;The advantages are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Don&#39;t Repeat Yourself (DRY)&lt;/li&gt;
&lt;li&gt;Fixes fixed in one place get propagated everywhere&lt;/li&gt;
&lt;li&gt;New features are just an &lt;code&gt;npm update&lt;/code&gt; away&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So, I&#39;ll proceed with 3 steps:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Create a TypeScript package&lt;/li&gt;
&lt;li&gt;Write some code&lt;/li&gt;
&lt;li&gt;Publish the module in NPM&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Let&#39;s see exactly how to do this. FYI, I am following these instructions on the current NodeJS LTS, version 16.&lt;/p&gt;
&lt;h2 id=&quot;1-create-a-type-script-package&quot;&gt;1. Create a TypeScript package &lt;a class=&quot;direct-link&quot; href=&quot;https://cmolina.dev/posts/2020/07/publish-typescript-package/#1-create-a-type-script-package&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I will be creating a new directory, to then set it up as an npm package and TypeScript project. All these changes will be tracked with git.&lt;/p&gt;
&lt;h3 id=&quot;1-1-initialize-an-npm-package&quot;&gt;1.1 Initialize an npm package &lt;a class=&quot;direct-link&quot; href=&quot;https://cmolina.dev/posts/2020/07/publish-typescript-package/#1-1-initialize-an-npm-package&quot;&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Create a directory for your package and start a npm package in it&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;mkdir&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;your-package-name&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token builtin class-name&quot;&gt;cd&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;your-package-name&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;npm&lt;/span&gt; init -y&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Ensure your new &lt;code&gt;package.json&lt;/code&gt; file contains at least this configuration (remember to update &lt;code&gt;name&lt;/code&gt;, &lt;code&gt;description&lt;/code&gt;, &lt;code&gt;author&lt;/code&gt; and &lt;code&gt;license&lt;/code&gt;):&lt;/p&gt;
&lt;div class=&quot;code-filename&quot;&gt;package.json&lt;/div&gt;
&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;your-package-name&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;version&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;0.1.0&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;description&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;What does this package do?&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;files&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;dist&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;main&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;dist/index.js&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;types&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;dist/index.d.ts&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;scripts&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token property&quot;&gt;&quot;prepublishOnly&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;tsc&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token property&quot;&gt;&quot;test&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;mocha test/**/*.spec.ts&quot;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;author&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;You &amp;lt;you@email.com&gt; (https://you.com/)&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;license&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;MIT&quot;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you are curious on the meaning of these properties, checkout the &lt;a href=&quot;https://docs.npmjs.com/cli/v7/configuring-npm/package-json&quot;&gt;excellent documentation for package.json&lt;/a&gt; from npm.&lt;/p&gt;
&lt;p&gt;This is also a good time to install your dependencies. There are 2 types:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;devDependencies&lt;/code&gt;, i.e. packages needed during development to build and test your library, and&lt;/li&gt;
&lt;li&gt;&lt;code&gt;dependencies&lt;/code&gt;, i.e. packages that &lt;em&gt;need to be deployed alongside your library&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For this example, I will require the following &lt;code&gt;devDependencies&lt;/code&gt; for:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;transpiling TypeScript files for production and testing, &lt;code&gt;typescript&lt;/code&gt; and &lt;code&gt;ts-node&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;my favorite test framework and assertion library, &lt;code&gt;mocha&lt;/code&gt; and &lt;code&gt;chai&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;their types annotations (&lt;code&gt;@types&lt;/code&gt;), for a better TypeScript experience.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;npm&lt;/span&gt; i -D &lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt;&lt;br /&gt;    typescript ts-node &lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt;&lt;br /&gt;    mocha chai &lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt;&lt;br /&gt;    @types/chai @types/mocha&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;1-2-initialize-a-type-script-project&quot;&gt;1.2 Initialize a TypeScript project &lt;a class=&quot;direct-link&quot; href=&quot;https://cmolina.dev/posts/2020/07/publish-typescript-package/#1-2-initialize-a-type-script-project&quot;&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Let&#39;s initialize a TypeScript project by creating a new file, named &lt;code&gt;tsconfig.json&lt;/code&gt;, that contains at least this configuration:&lt;/p&gt;
&lt;div class=&quot;code-filename&quot;&gt;tsconfig.json&lt;/div&gt;
&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;include&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;src/**/*&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;ts-node&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token property&quot;&gt;&quot;transpileOnly&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;   &lt;span class=&quot;token comment&quot;&gt;/* Skips type checking for faster unit testing */&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;compilerOptions&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token property&quot;&gt;&quot;declaration&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;    &lt;span class=&quot;token comment&quot;&gt;/* Generates corresponding &#39;.d.ts&#39; file. */&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token property&quot;&gt;&quot;outDir&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;./dist/&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;    &lt;span class=&quot;token comment&quot;&gt;/* Redirect output structure to the directory. */&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;1-3-configure-mocha&quot;&gt;1.3 Configure mocha &lt;a class=&quot;direct-link&quot; href=&quot;https://cmolina.dev/posts/2020/07/publish-typescript-package/#1-3-configure-mocha&quot;&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Before running the tests, let&#39;s configure mocha so it understands TypeScript files. Create a new &lt;code&gt;.mocharc.jsonc&lt;/code&gt; file with this configuration:&lt;/p&gt;
&lt;div class=&quot;code-filename&quot;&gt;.mocharc.jsonc&lt;/div&gt;
&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;require&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;ts-node/register&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;extension&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;ts&quot;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Without this file, trying to run the unit tests will fail with the following message:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;SyntaxError: Cannot use &lt;span class=&quot;token function&quot;&gt;import&lt;/span&gt; statement outside a module&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;1-4-track-changes-with-git&quot;&gt;1.4 Track changes with git &lt;a class=&quot;direct-link&quot; href=&quot;https://cmolina.dev/posts/2020/07/publish-typescript-package/#1-4-track-changes-with-git&quot;&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;First, initialize a git repository in the root of the package:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; init&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then, create a new file named &lt;code&gt;.gitignore&lt;/code&gt; to instruct git to ignore two directories, &lt;code&gt;node_modules&lt;/code&gt; and &lt;code&gt;dist&lt;/code&gt; for the dependencies and compiled files, respectively.&lt;/p&gt;
&lt;div class=&quot;code-filename&quot;&gt;.gitignore&lt;/div&gt;
&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;node_modules&lt;br /&gt;dist&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Make sure to keep track of these changes with git: &lt;code&gt;git add . &amp;amp;&amp;amp; git commit -m &amp;quot;New npm package&amp;quot;&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;2-write-some-code&quot;&gt;2. Write some code &lt;a class=&quot;direct-link&quot; href=&quot;https://cmolina.dev/posts/2020/07/publish-typescript-package/#2-write-some-code&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;At this point, we can start writing code and its tests. About time!&lt;/p&gt;
&lt;p&gt;Create a new file, &lt;code&gt;src/index.ts&lt;/code&gt;, and write some code. For example, export a function that sums two numbers:&lt;/p&gt;
&lt;div class=&quot;code-filename&quot;&gt;src/index.ts&lt;/div&gt;
&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;sum&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;a&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; b&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; a &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; b&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For the tests, you can create a spec under the &lt;code&gt;test&lt;/code&gt; directory, one &lt;code&gt;.spec.ts&lt;/code&gt; file for each source code file.&lt;/p&gt;
&lt;div class=&quot;code-filename&quot;&gt;test/index.spec.ts&lt;/div&gt;
&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; expect &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;chai&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; sum &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;../src/index&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;describe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;sum&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token function&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;should return the sum of 2 positive numbers&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token function&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;sum&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;to&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;equal&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now you are ready to run &lt;code&gt;npm test&lt;/code&gt; and see your test passing. If everything went well make a new commit: &lt;code&gt;git add . &amp;amp;&amp;amp; git commit -m &amp;quot;Initial code, unit test passing&amp;quot;&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;3-publish-a-module-in-npm&quot;&gt;3. Publish a module in NPM &lt;a class=&quot;direct-link&quot; href=&quot;https://cmolina.dev/posts/2020/07/publish-typescript-package/#3-publish-a-module-in-npm&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;You will need to log in with your npm account (and create one if you don&#39;t have it yet), ensure everything looks good, and finally publishing your package.&lt;/p&gt;
&lt;h3 id=&quot;3-1-login-to-npm-cli&quot;&gt;3.1 Login to npm CLI &lt;a class=&quot;direct-link&quot; href=&quot;https://cmolina.dev/posts/2020/07/publish-typescript-package/#3-1-login-to-npm-cli&quot;&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;If you do not already have an npm account, go to &lt;a href=&quot;https://www.npmjs.com/signup&quot;&gt;https://www.npmjs.com/signup&lt;/a&gt; and fill the form.&lt;/p&gt;
&lt;p&gt;In a terminal run &lt;code&gt;npm login&lt;/code&gt; and fill with your username and password when requested.&lt;/p&gt;
&lt;h3 id=&quot;3-2-update-your-package-name-optional-recommended&quot;&gt;3.2 Update your package name (optional, recommended) &lt;a class=&quot;direct-link&quot; href=&quot;https://cmolina.dev/posts/2020/07/publish-typescript-package/#3-2-update-your-package-name-optional-recommended&quot;&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Every time a package is published in npm it goes directly into the global scope. And because every package needs to have a unique name, it can be challenging to find an available name for your new package.&lt;/p&gt;
&lt;p&gt;To avoid this problem I recommend publishing your package under your username scope (or an org scope if you belong to one). To do this, go back to your &lt;code&gt;package.json&lt;/code&gt; and change the &lt;code&gt;name&lt;/code&gt; property,&lt;/p&gt;
&lt;div class=&quot;code-filename&quot;&gt;package.json&lt;/div&gt;
&lt;pre class=&quot;language-diff&quot;&gt;&lt;code class=&quot;language-diff&quot;&gt;{&lt;br /&gt;&lt;span class=&quot;token deleted-sign deleted&quot;&gt;&lt;span class=&quot;token prefix deleted&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token line&quot;&gt;    &quot;name&quot;: &quot;&amp;lt;your-package-name&gt;&quot;,&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token inserted-sign inserted&quot;&gt;&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;token line&quot;&gt;    &quot;name&quot;: &quot;@&amp;lt;your-username&gt;/&amp;lt;your-package-name&gt;&quot;,&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token unchanged&quot;&gt;&lt;span class=&quot;token prefix unchanged&quot;&gt; &lt;/span&gt;&lt;span class=&quot;token line&quot;&gt;   // ...&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;}&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;3-3-ensure-you-have-correctly-emitted-types&quot;&gt;3.3 Ensure you have correctly emitted types &lt;a class=&quot;direct-link&quot; href=&quot;https://cmolina.dev/posts/2020/07/publish-typescript-package/#3-3-ensure-you-have-correctly-emitted-types&quot;&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Now that you have your code written and tested, it is time to publish it. To see if everything is in order,&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;run &lt;code&gt;npm link&lt;/code&gt; to make your unpublished package available locally&lt;/li&gt;
&lt;li&gt;in another directory, run &lt;code&gt;npm link @&amp;lt;your-username&amp;gt;/&amp;lt;your-package-name&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;create an &lt;code&gt;index.ts&lt;/code&gt; file, and try to import the functions from your package&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;If everything went well, you will see the editor consuming the types you had specified 😁&lt;/p&gt;
&lt;h3 id=&quot;3-4-add-a-tag&quot;&gt;3.4 Add a tag &lt;a class=&quot;direct-link&quot; href=&quot;https://cmolina.dev/posts/2020/07/publish-typescript-package/#3-4-add-a-tag&quot;&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;People usually add tags to their git commits associated with a new version of a package so it can be easily referenced later: &lt;code&gt;git tag v0.1.0&lt;/code&gt;&lt;/p&gt;
&lt;h3 id=&quot;3-5-publish-it&quot;&gt;3.5 Publish it! &lt;a class=&quot;direct-link&quot; href=&quot;https://cmolina.dev/posts/2020/07/publish-typescript-package/#3-5-publish-it&quot;&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Run &lt;code&gt;npm publish --access public&lt;/code&gt;. This &lt;code&gt;access&lt;/code&gt; parameter indicates you will publish your package for everyone with access to npm.&lt;/p&gt;
&lt;p&gt;If no errors were published in the terminal, you should be able to see your package listed under &lt;code&gt;https://www.npmjs.com/package/@&amp;lt;your-username&amp;gt;/&amp;lt;your-package-name&amp;gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;For example, I followed the instructions from this post to publish a logging library mentioned in &lt;a href=&quot;https://cmolina.dev/posts/logging-functions/&quot;&gt;a previous post&lt;/a&gt; and this is the URL of the package: &lt;a href=&quot;https://www.npmjs.com/package/@cmolina/log&quot;&gt;https://www.npmjs.com/package/@cmolina/log&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&quot;3-6-publish-an-update&quot;&gt;3.6 Publish an update &lt;a class=&quot;direct-link&quot; href=&quot;https://cmolina.dev/posts/2020/07/publish-typescript-package/#3-6-publish-an-update&quot;&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;After publishing the first version of the package you may be wondering how to send an update. Well, you have to commit your changes, ensure every test is passing, compiling, bumping the version, adding a tag… it is pretty easy to forget a step.&lt;/p&gt;
&lt;p&gt;Good news we have &lt;code&gt;np&lt;/code&gt;, an npm package for publishing to npm.&lt;/p&gt;
&lt;p&gt;After committing your changes, run &lt;code&gt;npx np&lt;/code&gt; and answer the questions. The first time I run it I had to update &lt;code&gt;npm&lt;/code&gt; and made me have a remote repository as well (I chose GitHub).&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion &lt;a class=&quot;direct-link&quot; href=&quot;https://cmolina.dev/posts/2020/07/publish-typescript-package/#conclusion&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;You learned how to create a TypeScript library from scratch, how to manually publishing a new npm package, and to keep it up to date.&lt;/p&gt;
&lt;p&gt;Happy publishing!&lt;/p&gt;

			
		</content>
	</entry>
	
	<entry>
		<title>Create a dark theme</title>
		<link href="https://cmolina.dev/posts/2020/09/create-dark-theme/"/>
		<updated>2020-09-30T00:00:00Z</updated>
		<id>https://cmolina.dev/posts/2020/09/create-dark-theme/</id>
		<content type="html">
		  &lt;p&gt;I&#39;ve been interested in implementing a dark theme for my blog. I like websites that respect the user preference of using dark themes and was feeling sorry that my blog was always so bright.&lt;/p&gt;
&lt;p&gt;Even when I use the &lt;a href=&quot;https://darkreader.org/&quot;&gt;DarkReader extension&lt;/a&gt; for those pages that don&#39;t include a dark mode, which makes a marvelous job by the way— some edge cases made my blog look odd and hard to read. That&#39;s why I decided to document the steps to share my learning.&lt;/p&gt;
&lt;p&gt;I implemented a dark mode in 3 steps,&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Define my colors in a single place&lt;/li&gt;
&lt;li&gt;Redefine my colors for the dark theme&lt;/li&gt;
&lt;li&gt;Test for accessibility&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;1-define-my-colors-in-a-single-place&quot;&gt;1. Define my colors in a single place &lt;a class=&quot;direct-link&quot; href=&quot;https://cmolina.dev/posts/2020/09/create-dark-theme/#1-define-my-colors-in-a-single-place&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In the beginning, the colors were defined and redefined all over my CSS. Before implementing my dark theme, I collected the colors used in my &lt;em&gt;light&lt;/em&gt; theme, defined new CSS variables for the &lt;code&gt;:root&lt;/code&gt; element, and used these variables instead of hardcoded values.&lt;/p&gt;
&lt;p&gt;The reason for doing this change is that is going to make it easier later to identify which colors belong to the default/light theme, and which overrides are necessary for the dark theme.&lt;/p&gt;
&lt;p&gt;At the beginning of your stylesheet, you can write something like this&lt;/p&gt;
&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;/* default colors are defined here */&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token selector&quot;&gt;:root&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;--background&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; #fff&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;--color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; #000&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;/* and then can be referenced using `var(--custom-color)` */&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token selector&quot;&gt;body&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;background&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;--background&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;--color&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;2-redefine-my-colors-for-the-dark-theme&quot;&gt;2. Redefine my colors for the dark theme &lt;a class=&quot;direct-link&quot; href=&quot;https://cmolina.dev/posts/2020/09/create-dark-theme/#2-redefine-my-colors-for-the-dark-theme&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Now that all the colors are defined in a single place, add a media query for &lt;code&gt;prefers-color-scheme: dark&lt;/code&gt; where you redefine the variables as needed.&lt;/p&gt;
&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;/* default colors are defined here */&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token selector&quot;&gt;:root&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;--background&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; #fff&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;--color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; #000&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;/* dark theme overrides */&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token atrule&quot;&gt;&lt;span class=&quot;token rule&quot;&gt;@media&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;prefers-color-scheme&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; dark&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token selector&quot;&gt;:root&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token property&quot;&gt;--background&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; #333&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token property&quot;&gt;--color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; #fff&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To see the changes in your browser you need to &lt;a href=&quot;https://www.theverge.com/2019/3/22/18270975/how-to-dark-mode-iphone-android-mac-windows-xbox-ps4-nintendo-switch&quot;&gt;enable dark mode&lt;/a&gt; for the device you are working on.&lt;/p&gt;
&lt;p&gt;As I don&#39;t have formal studies in design it was hard for me to choose all the colors from scratch; I ended up using the suggested colors given by DarkReader and then manually tweak them until I was happy with the results.&lt;/p&gt;
&lt;p&gt;There are excellent guides on how to choose the colors for a dark theme. I recommend reading the &lt;a href=&quot;https://material.io/design/color/dark-theme.html&quot;&gt;Material Design guide&lt;/a&gt; and &lt;a href=&quot;https://developer.apple.com/design/human-interface-guidelines/ios/visual-design/dark-mode&quot;&gt;Apple&#39;s Dark mode guide&lt;/a&gt;. I learned from them that it was wise to set the background with gray instead of black, as very high contrast colors can negatively affect the readability; and that you can use increasingly lighter colors for the background to reflect elevated layers. Check them out.&lt;/p&gt;
&lt;h2 id=&quot;3-test-for-accessibility&quot;&gt;3. Test for accessibility &lt;a class=&quot;direct-link&quot; href=&quot;https://cmolina.dev/posts/2020/09/create-dark-theme/#3-test-for-accessibility&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Once you are happy with the light and dark colors you have chosen, now it is time to ensure they have enough contrast so all users can read your website.&lt;/p&gt;
&lt;p&gt;The main suggestion here is to ensure the contrast between background and foreground color is visible enough, for both the light and the dark theme. The WCAG 2.0 level AA recommends a contrast of &lt;strong&gt;4.5&lt;/strong&gt; : 1. I personally like to check the contrast by using the &lt;a href=&quot;https://webaim.org/resources/contrastchecker/&quot;&gt;WebAIM&#39;s contrast checker tool&lt;/a&gt; for individual colors or to scan the whole website with the &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Tools/Accessibility_inspector&quot;&gt;Accessibility Inspector included in Firefox DevTools&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;focus-indicator&quot;&gt;Focus indicator &lt;a class=&quot;direct-link&quot; href=&quot;https://cmolina.dev/posts/2020/09/create-dark-theme/#focus-indicator&quot;&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;On my first dark theme implementation, I totally forgot about ensuring the focus indicators were actually visible. The one that is provided by browsers is not always visible enough (&lt;em&gt;I am talking about you, Firefox&lt;/em&gt;), and it could be hard to detect depending on the theme of your website. You can define your custom focus indicator like this:&lt;/p&gt;
&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token selector&quot;&gt;:focus&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;outline&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; thick solid &lt;span class=&quot;token function&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;--primary-color&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;  &lt;span class=&quot;token comment&quot;&gt;/* ensure the color works for both themes */&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;outline-offset&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; .3rem&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;conclusion&quot;&gt;Conclusion &lt;a class=&quot;direct-link&quot; href=&quot;https://cmolina.dev/posts/2020/09/create-dark-theme/#conclusion&quot;&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;In this article I presented a technique to keep your website theme to respect the customer preference of either light or dark theme, being careful of choosing colors that all people can read. Did you notice the new dark theme from the blog? Are there any other things you should be thinking of?&lt;/p&gt;

			
		</content>
	</entry>
	
	<entry>
		<title>Migrating away from hey.com</title>
		<link href="https://cmolina.dev/posts/2021/05/migrating-from-hey/"/>
		<updated>2021-05-04T00:00:00Z</updated>
		<id>https://cmolina.dev/posts/2021/05/migrating-from-hey/</id>
		<content type="html">
		  &lt;p&gt;I really like the Hey email client. I am a customer since July 2020 and after onboarding, I&#39;ve experienced less time managing my emails and more time doing things I love.&lt;/p&gt;
&lt;p&gt;I will not expand in this post why I can&#39;t trust Basecamp anymore (the company that builds Hey) as it has already been said &lt;a href=&quot;https://marker.medium.com/basecamp-is-failing-its-own-future-d487bed43155&quot;&gt;multiple times&lt;/a&gt; by &lt;a href=&quot;https://breen.tech/post/cringe-camp/&quot;&gt;so&lt;/a&gt; &lt;a href=&quot;https://internet-work.co/my-answer-to-the-ceo-of-basecamp-about-the-ban-on-political-talks/&quot;&gt;many&lt;/a&gt; &lt;a href=&quot;https://usefathom.com/podcast/basecamp&quot;&gt;people&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;What I will do is to explain how I stopped using Hey, and what is my new email configuration (which is mimicking Hey to a certain extent). Let&#39;s get started.&lt;/p&gt;
&lt;h2 id=&quot;high-level-overview&quot;&gt;High level overview &lt;a class=&quot;direct-link&quot; href=&quot;https://cmolina.dev/posts/2021/05/migrating-from-hey/#high-level-overview&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I chose &lt;a href=&quot;https://protonmail.com/&quot;&gt;Protonmail&lt;/a&gt; as my new email provider, together with a custom domain, a single rule filter for replicating the screening, 3 custom folders, and the built-in contacts and mark as spam features.&lt;/p&gt;
&lt;p&gt;The new Inbox looks like this:&lt;br /&gt;
&lt;img src=&quot;https://cmolina.dev/img/2021/05/protonmail-screenshot.png&quot; alt=&quot;A screenshot of the Protonmail web client&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Did you notice the &amp;quot;Paper trail&amp;quot;, &amp;quot;Screening&amp;quot; and &amp;quot;The Feed&amp;quot; folders?&lt;/p&gt;
&lt;p&gt;Still interested? Let&#39;s jump to the details.&lt;/p&gt;
&lt;h2 id=&quot;1-sign-up-for-a-protonmail-account&quot;&gt;1. Sign up for a Protonmail account &lt;a class=&quot;direct-link&quot; href=&quot;https://cmolina.dev/posts/2021/05/migrating-from-hey/#1-sign-up-for-a-protonmail-account&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I was looking for an email provider which:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I could mimic Hey screening&lt;/li&gt;
&lt;li&gt;I could believe in their mission and I wouldn&#39;t have to run away from&lt;/li&gt;
&lt;li&gt;I could keep my email in the case of the provider becoming evil&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Protonmail is an open source product, with a focus on privacy and to protect civil liberties online. It is free to use, but this guide assumes you buy the &lt;a href=&quot;https://protonmail.com/pricing&quot;&gt;Plus plan, starting at €48.00 a year&lt;/a&gt;, as I will be using paid features.&lt;/p&gt;
&lt;p&gt;First &lt;a href=&quot;https://protonmail.com/signup&quot;&gt;I had to create&lt;/a&gt; a &lt;a href=&quot;http://protonmail.com/&quot;&gt;protonmail.com&lt;/a&gt; account. The process is super straightforward, and you can create a free account and upgrade later when needed.&lt;/p&gt;
&lt;p&gt;After I had my new account created, I proceeded to get a cool email alias with a custom domain.&lt;/p&gt;
&lt;h2 id=&quot;2-get-an-email-with-a-custom-domain-optional&quot;&gt;2. Get an email with a custom domain (optional) &lt;a class=&quot;direct-link&quot; href=&quot;https://cmolina.dev/posts/2021/05/migrating-from-hey/#2-get-an-email-with-a-custom-domain-optional&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;One of the nice things of Hey was the possibility of choosing a short email address.&lt;/p&gt;
&lt;p&gt;Since Protonmail supports custom domains for paid accounts —and I already have a domain for my blog— I decided to replicate this feature; I replaced my legacy email &lt;code&gt;cmolina@hey.com&lt;/code&gt; with the new &lt;code&gt;hi@cmolina.dev&lt;/code&gt;. One less character to write!&lt;/p&gt;
&lt;p&gt;The instructions to &lt;a href=&quot;https://protonmail.com/support/knowledge-base/set-up-a-custom-domain/&quot;&gt;configure a custom domain are here&lt;/a&gt;. You will need to set some DNS settings, which sounds hard but the ProtonMail documentation has instructions for the most common domain registrars.&lt;/p&gt;
&lt;p&gt;Notice that the changes in DNS may take hours or even days to complete; meanwhile I recommend you to keep going with this guide.&lt;/p&gt;
&lt;h2 id=&quot;2-replicating-the-screening&quot;&gt;2. Replicating the Screening &lt;a class=&quot;direct-link&quot; href=&quot;https://cmolina.dev/posts/2021/05/migrating-from-hey/#2-replicating-the-screening&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Let&#39;s configure Protonmail to emulate the Screening feature by following 3 steps.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Go to &lt;a href=&quot;https://mail.protonmail.com/labels&quot;&gt;Folder/Labels link&lt;/a&gt; and create 3 folders: &amp;quot;Screening&amp;quot;, &amp;quot;Paper trail&amp;quot;, and &amp;quot;The Feed&amp;quot;.&lt;/p&gt;
&lt;p&gt;I decided to on purpose not to create an &amp;quot;Imbox&amp;quot; folder and use the existing &amp;quot;Inbox&amp;quot; (finally I am not reading that typo anymore!).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Go to &lt;a href=&quot;https://mail.protonmail.com/contacts&quot;&gt;Contacts&lt;/a&gt; and create 3 contact groups: &amp;quot;InboxGroup&amp;quot;, &amp;quot;TheFeedGroup&amp;quot;, and &amp;quot;PaperTrailGroup&amp;quot;.&lt;/p&gt;
&lt;p&gt;The idea here is every time you get an email from an unknown sender, you can accept new messages by adding the sender to one of those contact groups; and to screen off you use the &amp;quot;Mark as spam&amp;quot; feature.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Go to &lt;a href=&quot;https://mail.protonmail.com/filters&quot;&gt;Settings &amp;gt; Filters&lt;/a&gt; and click &amp;quot;Add Sieve filter&amp;quot;.&lt;/p&gt;
&lt;p&gt;Create a new Sieve filter named &amp;quot;Mimic the Screening&amp;quot; with the following script:&lt;/p&gt;
&lt;pre class=&quot;language-c&quot;&gt;&lt;code class=&quot;language-c&quot;&gt;require &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;include&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;environment&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;variables&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;relational&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;comparator-i;ascii-numeric&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;spamtest&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;extlists&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;fileinto&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;imap4flags&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;token expression&quot;&gt;Generated&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Do not run this script on spam messages&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;allof&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;environment &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;matches &lt;span class=&quot;token string&quot;&gt;&quot;vnd.proton.spam-threshold&quot;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;*&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; spamtest &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;value &lt;span class=&quot;token string&quot;&gt;&quot;ge&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;comparator &lt;span class=&quot;token string&quot;&gt;&quot;i;ascii-numeric&quot;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;${1}&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;token expression&quot;&gt;Ignore messages sent by myself&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; they will be stored in `Sent`&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; header &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;list &lt;span class=&quot;token string&quot;&gt;&quot;from&quot;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;:addrbook:myself&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;token expression&quot;&gt;Mimicking the Screening&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; header &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;list &lt;span class=&quot;token string&quot;&gt;&quot;from&quot;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;:addrbook:personal?label=InboxGroup&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    fileinto &lt;span class=&quot;token string&quot;&gt;&quot;Inbox&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;elsif header &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;list &lt;span class=&quot;token string&quot;&gt;&quot;from&quot;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;:addrbook:personal?label=TheFeedGroup&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    addflag &lt;span class=&quot;token string&quot;&gt;&quot;\\Seen&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    fileinto &lt;span class=&quot;token string&quot;&gt;&quot;The feed&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;elsif header &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;list &lt;span class=&quot;token string&quot;&gt;&quot;from&quot;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;:addrbook:personal?label=PaperTrailGroup&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    fileinto &lt;span class=&quot;token string&quot;&gt;&quot;Paper trail&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    fileinto &lt;span class=&quot;token string&quot;&gt;&quot;Screening&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The code is pretty much self-explanatory: known senders will be moved to the corresponding folder, otherwise it will go to Screening. I also decided to mark every email under &amp;quot;The Feed&amp;quot; as seen. To learn more about the syntax you can read the &lt;a href=&quot;https://protonmail.com/support/knowledge-base/sieve-advanced-custom-filters/&quot;&gt;Sieve filter guide&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;After this, the only pending step is to instruct Hey to forward the emails to the new email.&lt;/p&gt;
&lt;h2 id=&quot;3-enabling-email-forwarding-in-hey&quot;&gt;3. Enabling email forwarding in Hey &lt;a class=&quot;direct-link&quot; href=&quot;https://cmolina.dev/posts/2021/05/migrating-from-hey/#3-enabling-email-forwarding-in-hey&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Eventually, I will have to change every account linked to my previous @hey.com account. But for now, I need to instruct Hey to forward every new message to my new address.&lt;/p&gt;
&lt;p&gt;In &lt;a href=&quot;http://app.hey.com/&quot;&gt;app.hey.com&lt;/a&gt;, go to &amp;quot;Me&amp;quot; &amp;gt; &amp;quot;Account Setup&amp;quot; &amp;gt; &amp;quot;Forwarding &amp;amp; SMTP Setup&amp;quot; &amp;gt; &amp;quot;Forward email out of HEY&amp;quot;.&lt;/p&gt;
&lt;p&gt;Write your new email address. You will receive an email in Protonmail to confirm the operation.&lt;/p&gt;
&lt;h2 id=&quot;4-importing-the-emails-from-hey&quot;&gt;4. Importing the emails from Hey &lt;a class=&quot;direct-link&quot; href=&quot;https://cmolina.dev/posts/2021/05/migrating-from-hey/#4-importing-the-emails-from-hey&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;You probably want to be able to access all your emails from an unique account. The good news is that you can bring all your emails from Hey —and the search engine is way better!&lt;/p&gt;
&lt;p&gt;To export your emails, in &lt;a href=&quot;http://app.hey.com/&quot;&gt;app.hey.com&lt;/a&gt;, go to &amp;quot;Me&amp;quot; &amp;gt; &amp;quot;Account Setup&amp;quot; &amp;gt; &amp;quot;Export your data&amp;quot; &amp;gt; &amp;quot;Export my emails&amp;quot;. In a few minutes you will receive an email with a MBOX file.&lt;/p&gt;
&lt;p&gt;To import the MBOX file to Protonmail, install their &lt;a href=&quot;https://protonmail.com/import-export&quot;&gt;Import Export app&lt;/a&gt;. You can read the &lt;a href=&quot;https://protonmail.com/support/knowledge-base/how-to-import-emails-to-your-protonmail-account/&quot;&gt;detailed instructions here&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;5-canceling-your-hey-subscription&quot;&gt;5. Canceling your Hey subscription &lt;a class=&quot;direct-link&quot; href=&quot;https://cmolina.dev/posts/2021/05/migrating-from-hey/#5-canceling-your-hey-subscription&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Canceling a Hey account allows you to stop paying the service, but you still can read emails, export emails and contacts, and update the forwarding configuration (at least until Basecamp discontinues the service).&lt;/p&gt;
&lt;p&gt;In &lt;a href=&quot;http://app.hey.com/&quot;&gt;app.hey.com&lt;/a&gt;, go to &amp;quot;Me&amp;quot; &amp;gt; &amp;quot;Account Setup&amp;quot; &amp;gt; &amp;quot;Billing &amp;amp; Invoices&amp;quot; in order to cancel your subscription.&lt;/p&gt;
&lt;h2 id=&quot;wrapping-up&quot;&gt;Wrapping up &lt;a class=&quot;direct-link&quot; href=&quot;https://cmolina.dev/posts/2021/05/migrating-from-hey/#wrapping-up&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I&#39;ve been using this configuration for a month now and I can truly say I am having a great time with my emails.&lt;/p&gt;
&lt;p&gt;An unexpected benefit of going to Protonmail is the ability to &lt;em&gt;archive&lt;/em&gt; emails: I don&#39;t need to keep my Inbox full of already read emails, but only of unread and &lt;em&gt;reply later&lt;/em&gt; messages.&lt;/p&gt;
&lt;h3 id=&quot;the-good&quot;&gt;The good &lt;a class=&quot;direct-link&quot; href=&quot;https://cmolina.dev/posts/2021/05/migrating-from-hey/#the-good&quot;&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;Is it possible to enjoy your email without supporting Basecamp?&lt;/em&gt; Yes. The most valuable feature of Hey, the Screening, works as expected&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Is it possible to keep your new email address across providers?&lt;/em&gt; Yes, I still receive emails from my legacy Hey account, and my new email address won&#39;t change if I ever decide to migrate from Protonmail&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Will be less expensive?&lt;/em&gt; Yes, as of today it will be at least $41 cheaper, a hefty 40% discount&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;the-bad&quot;&gt;The bad &lt;a class=&quot;direct-link&quot; href=&quot;https://cmolina.dev/posts/2021/05/migrating-from-hey/#the-bad&quot;&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;As of today, classifying new emails into Inbox/The Feed/Paper trail is somewhat cumbersome. It involves 4 manual steps:
&lt;ol&gt;
&lt;li&gt;create a contact,&lt;/li&gt;
&lt;li&gt;add the contact to one of the contact groups,&lt;/li&gt;
&lt;li&gt;go back to the email, and&lt;/li&gt;
&lt;li&gt;manually move the message to its corresponding folder.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;the-ugly&quot;&gt;The ugly &lt;a class=&quot;direct-link&quot; href=&quot;https://cmolina.dev/posts/2021/05/migrating-from-hey/#the-ugly&quot;&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Apparently &lt;a href=&quot;https://protonmail.com/support/knowledge-base/contact-groups/&quot;&gt;there is a limit of 100 contacts&lt;/a&gt; that a single contact group can handle&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I imagine a workaround where I can keep creating contact groups while I update the Sieve filter, but I&#39;d prefer not to. Anyway, I am not close to reach the limit yet.&lt;/p&gt;
&lt;p&gt;I &lt;a href=&quot;https://github.com/ProtonMail/WebClient/issues/190&quot;&gt;commented on an existing issue&lt;/a&gt; to understand what are my options but the developers haven&#39;t answered yet. I will keep this post up-to-date.&lt;/p&gt;

			
		</content>
	</entry>
	
	<entry>
		<title>Configuring git for the first time</title>
		<link href="https://cmolina.dev/posts/2021/06/configure-git/"/>
		<updated>2021-06-14T00:00:00Z</updated>
		<id>https://cmolina.dev/posts/2021/06/configure-git/</id>
		<content type="html">
		  &lt;p&gt;Hey, do you have a new development laptop and do you need to configure git? I always need to run the same commands, but I do it so rarely that I always forget how to do it properly.&lt;/p&gt;
&lt;p&gt;This article is a guide for my Future Me. &lt;em&gt;You are welcome, Future Carlos!&lt;/em&gt;&lt;/p&gt;
&lt;h2 id=&quot;set-my-name-and-email&quot;&gt;Set my name and email &lt;a class=&quot;direct-link&quot; href=&quot;https://cmolina.dev/posts/2021/06/configure-git/#set-my-name-and-email&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This is the minimum you need to get started with git. Go ahead and execute it with your information:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; config --global user.name &lt;span class=&quot;token string&quot;&gt;&quot;My Name&quot;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; config --global user.email &lt;span class=&quot;token string&quot;&gt;&quot;me@example.com&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;enable-autocorrect-typos&quot;&gt;Enable autocorrect typos &lt;a class=&quot;direct-link&quot; href=&quot;https://cmolina.dev/posts/2021/06/configure-git/#enable-autocorrect-typos&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Did you know git can automatically correct your misspelled commands for you? By enabling this feature with:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; config --global help.autocorrect &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# time to delay, unit is 1/10th of a second&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;you will &lt;strong&gt;receive a suggestion with a correction&lt;/strong&gt; that will automatically execute after 1 second, unless you hit &lt;kbd&gt;Ctrl&lt;/kbd&gt; + &lt;kbd&gt;C&lt;/kbd&gt; —for example running &lt;code&gt;git sttus&lt;/code&gt; will print:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;WARNING: You called a Git &lt;span class=&quot;token builtin class-name&quot;&gt;command&lt;/span&gt; named &lt;span class=&quot;token string&quot;&gt;&#39;sttus&#39;&lt;/span&gt;, &lt;span class=&quot;token function&quot;&gt;which&lt;/span&gt; does not exist.&lt;br /&gt;Continuing &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1.0&lt;/span&gt; seconds, assuming that you meant &lt;span class=&quot;token string&quot;&gt;&#39;status&#39;&lt;/span&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;.&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;use-nano-as-the-default-editor&quot;&gt;Use nano as the default editor &lt;a class=&quot;direct-link&quot; href=&quot;https://cmolina.dev/posts/2021/06/configure-git/#use-nano-as-the-default-editor&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Someday I will learn how to use &lt;code&gt;vim&lt;/code&gt; (without rebooting my laptop because I didn&#39;t know how to close it). In the meantime I will use &lt;code&gt;nano&lt;/code&gt; instead:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; config --global core.editor &lt;span class=&quot;token string&quot;&gt;&quot;nano&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;use-visual-studio-code-for-squashing&quot;&gt;Use Visual Studio Code for squashing &lt;a class=&quot;direct-link&quot; href=&quot;https://cmolina.dev/posts/2021/06/configure-git/#use-visual-studio-code-for-squashing&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;So there is one disadvantage of using &lt;code&gt;nano&lt;/code&gt; as the default editor: when running &lt;code&gt;git rebase -i&lt;/code&gt; it can be pretty time-consuming to squash several commits, as I don&#39;t know how to replace multiple words yet.&lt;/p&gt;
&lt;p&gt;I prefer to use &lt;code&gt;vscode&lt;/code&gt; with the &lt;a href=&quot;https://marketplace.visualstudio.com/items?itemName=eamodio.gitlens&quot;&gt;GitLens extension&lt;/a&gt;; it can be setup with:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; config --global sequence.editor &lt;span class=&quot;token string&quot;&gt;&quot;code --wait&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;which will open a convenient rebase interactive tab when needed, like the one of the next screenshot:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cmolina.dev/img/2021/06/interactive-rebase-editor.png&quot; alt=&quot;Screenshot of GitLen&#39;s interactive rebase editor&quot; /&gt;&lt;/p&gt;
&lt;h2 id=&quot;change-your-default-branch-name&quot;&gt;Change your default branch name &lt;a class=&quot;direct-link&quot; href=&quot;https://cmolina.dev/posts/2021/06/configure-git/#change-your-default-branch-name&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The current version of git shows a warning when initializing a new repository with &lt;code&gt;git init&lt;/code&gt;, as they are moving away from &lt;code&gt;master&lt;/code&gt;. Since I prefer to use &lt;code&gt;main&lt;/code&gt;, I made the message disappear by running the following command:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; config --global init.defaultBranch main&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;choose-a-default-strategy-for-git-pull&quot;&gt;Choose a default strategy for &lt;code&gt;git pull&lt;/code&gt; &lt;a class=&quot;direct-link&quot; href=&quot;https://cmolina.dev/posts/2021/06/configure-git/#choose-a-default-strategy-for-git-pull&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I am lazy, and when I want to ensure I have the latest changes from a remote repo I just type &lt;code&gt;git pull&lt;/code&gt; —instead of &lt;code&gt;git pull --ff-only&lt;/code&gt; command which will bring any commits from origin with a fast-forward. However, this is what git outputs by default:&lt;/p&gt;
&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;Pulling without specifying how to reconcile divergent branches is&lt;br /&gt;discouraged. You can squelch this message by running one of the following&lt;br /&gt;commands sometime before your next pull:&lt;br /&gt;&lt;br /&gt;git config pull.rebase false  # merge (the default strategy)&lt;br /&gt;git config pull.rebase true   # rebase&lt;br /&gt;git config pull.ff only       # fast-forward only&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I use the third option, but feel free to pick your poison.&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; config --global pull.ff only&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;use-a-global-gitignore-file-optional&quot;&gt;Use a global .gitignore file (optional) &lt;a class=&quot;direct-link&quot; href=&quot;https://cmolina.dev/posts/2021/06/configure-git/#use-a-global-gitignore-file-optional&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I only had to use this feature once: when I was using a particular tool that generates files to be ignored, but because I was the only coworker using the tool &lt;em&gt;I was not supposed to modify the committed &lt;code&gt;.gitignore&lt;/code&gt; file&lt;/em&gt; 😒🤷🏽‍♂️🤨.&lt;/p&gt;
&lt;p&gt;I am sure this technique may be useful in other situations as well; to use it, run:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; config --global core.excludesfile &lt;span class=&quot;token string&quot;&gt;&quot;~/.gitignore&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And create &lt;code&gt;~/.gitignore&lt;/code&gt; with your favorite editor.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion &lt;a class=&quot;direct-link&quot; href=&quot;https://cmolina.dev/posts/2021/06/configure-git/#conclusion&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Hopefully you learned or rediscovered some cool things you can do with git 😄&lt;/p&gt;

			
		</content>
	</entry>
	
	<entry>
		<title>My terminal configuration</title>
		<link href="https://cmolina.dev/posts/2021/11/configure-terminal/"/>
		<updated>2021-11-25T00:00:00Z</updated>
		<id>https://cmolina.dev/posts/2021/11/configure-terminal/</id>
		<content type="html">
		  &lt;p&gt;Software developers can spend long periods of time in the terminal: installing dependencies, reading logs, exploring the file system and running build commands to name a few examples. For this reason, I wrote a compilation of programs that have made my life easier, by either&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;making easier to install the packages for my development needs,&lt;/li&gt;
&lt;li&gt;providing a custom experience (like custom fonts and syntax highlight), or&lt;/li&gt;
&lt;li&gt;typing less (with autocomplete and informative prompt).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Most of these programs are one of the first things I install when using a new laptop, like the &lt;em&gt;terminal emulator&lt;/em&gt; and &lt;em&gt;package manager&lt;/em&gt;; others, like the &lt;em&gt;ruby version manager&lt;/em&gt;, stay pending installation a bit longer until I actually require them.&lt;/p&gt;
&lt;p&gt;Currently, I am using a MacBook Air 2020 (M1 chip); however, most of these programs are either cross-platform, or they have an alternative in different OSs. Without further ado, here is my terminal configuration!&lt;/p&gt;
&lt;h2 id=&quot;terminal-emulator-i-term2&quot;&gt;Terminal emulator: iTerm2 &lt;a class=&quot;direct-link&quot; href=&quot;https://cmolina.dev/posts/2021/11/configure-terminal/#terminal-emulator-i-term2&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;https://cmolina.dev/img/2021/11/iTerm2-screenshot.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;I love its minimal UI, but at the same time it has lots of features and is very customizable. Particularly, I like to&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;split the screen (&lt;kbd&gt;Cmd&lt;/kbd&gt; + &lt;kbd&gt;D&lt;/kbd&gt;),&lt;/li&gt;
&lt;li&gt;open new tabs (&lt;kbd&gt;Cmd&lt;/kbd&gt; + &lt;kbd&gt;T&lt;/kbd&gt;), and&lt;/li&gt;
&lt;li&gt;set a profile for &amp;quot;Hotkey Window&amp;quot; (or always-available Guake-style terminal).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Get it from &lt;a href=&quot;https://iterm2.com/&quot;&gt;https://iterm2.com/&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;package-manager-homebrew&quot;&gt;Package manager: Homebrew &lt;a class=&quot;direct-link&quot; href=&quot;https://cmolina.dev/posts/2021/11/configure-terminal/#package-manager-homebrew&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;https://cmolina.dev/img/2021/11/brew-screenshot.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Package managers are so handy for code development. While I enjoyed them while using Linux, for some reason Mac and Windows don&#39;t come with one by default. And Homebrew is not perfect —it breaks from time to time, but it has a big community, and you can probably find a fix for your problem in Stack Overflow.&lt;/p&gt;
&lt;p&gt;I&#39;ve been curious on trying &lt;a href=&quot;http://pkgsrc.joyent.com/&quot;&gt;pkgsrc&lt;/a&gt; in the past, but I keep deprioritizing it, as it is not as popular as Homebrew and I don&#39;t feel like &lt;em&gt;living in the edge&lt;/em&gt; so much these days.&lt;/p&gt;
&lt;p&gt;I list Homebrew at the top of my list since it is the tool I use for installing the majority of the rest of the programs presented in this blog post.&lt;/p&gt;
&lt;p&gt;Get it from &lt;a href=&quot;https://brew.sh/&quot;&gt;https://brew.sh/&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;prompt-starship&quot;&gt;Prompt: Starship &lt;a class=&quot;direct-link&quot; href=&quot;https://cmolina.dev/posts/2021/11/configure-terminal/#prompt-starship&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;video autoplay=&quot;&quot; loop=&quot;&quot; playsinline=&quot;&quot;&gt;&lt;source src=&quot;https://cmolina.dev/img/2021/11/starship-demo.webm&quot; type=&quot;video/webm&quot; /&gt;&lt;/video&gt;&lt;/p&gt;
&lt;p&gt;While Starship is supposed to be fully customizable and cross-OS compatible, what I really love about this prompt is that it just works out of the box, particularly &lt;code&gt;git&lt;/code&gt; and &lt;code&gt;nodejs&lt;/code&gt; integrations. And it is fast —nobody likes to wait for the new terminal to be ready.&lt;/p&gt;
&lt;p&gt;I use it with &lt;a href=&quot;https://www.nerdfonts.com/&quot;&gt;FiraCode Nerd Font&lt;/a&gt;, which provide icons for different languages, and it looks awesome. I use the &lt;a href=&quot;https://starship.rs/presets/#bracketed-segments&quot;&gt;bracketed segment preset&lt;/a&gt; as well.&lt;/p&gt;
&lt;p&gt;Get it from Homebrew, and read the docs at &lt;a href=&quot;https://starship.rs/&quot;&gt;https://starship.rs/&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;replacements&quot;&gt;Replacements &lt;a class=&quot;direct-link&quot; href=&quot;https://cmolina.dev/posts/2021/11/configure-terminal/#replacements&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Some tools within a UNIX-like system are &lt;em&gt;ancient&lt;/em&gt;, and for compatibility or codebase reasons they can&#39;t improve and keep themselves modern. However, new programs do not have these limitations. Here I list a couple of alternatives to classic terminal programs.&lt;/p&gt;
&lt;h3 id=&quot;bat-a-cat-alternative&quot;&gt;bat: a &lt;code&gt;cat&lt;/code&gt; alternative &lt;a class=&quot;direct-link&quot; href=&quot;https://cmolina.dev/posts/2021/11/configure-terminal/#bat-a-cat-alternative&quot;&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://cmolina.dev/img/2021/11/bat-screenshot.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;What if you could read files with syntax highlight directly from your terminal? I&#39;ve always used &lt;code&gt;cat&lt;/code&gt; to read files, however it is hard to read code with no colors and no scroll. (Maybe &lt;code&gt;vim&lt;/code&gt; users can already do this, but I still have no idea how to exit that program 🥲).&lt;/p&gt;
&lt;p&gt;This is why I like &lt;code&gt;bat&lt;/code&gt; so much. However, since I am already used to type &lt;code&gt;cat&lt;/code&gt;, I made an &lt;em&gt;alias&lt;/em&gt; to use &lt;code&gt;bat&lt;/code&gt; instead:&lt;/p&gt;
&lt;div class=&quot;code-filename&quot;&gt;~/.zshrc&lt;/div&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;alias&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;cat&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;bat&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Get it from Homebrew, and read the docs at &lt;a href=&quot;https://github.com/sharkdp/bat&quot;&gt;https://github.com/sharkdp/bat&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;exa-a-ls-alternative&quot;&gt;exa: a &lt;code&gt;ls&lt;/code&gt; alternative &lt;a class=&quot;direct-link&quot; href=&quot;https://cmolina.dev/posts/2021/11/configure-terminal/#exa-a-ls-alternative&quot;&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://cmolina.dev/img/2021/11/exa-screenshot.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;exa&lt;/code&gt; is way easier to read for me than &lt;code&gt;ls&lt;/code&gt;. Period. I also added an alias to replace &lt;code&gt;ls&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Get it from Homebrew, and read the docs at &lt;a href=&quot;https://github.com/ogham/exa&quot;&gt;https://github.com/ogham/exa&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;other-utilities&quot;&gt;Other utilities &lt;a class=&quot;direct-link&quot; href=&quot;https://cmolina.dev/posts/2021/11/configure-terminal/#other-utilities&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I just I don&#39;t know how to classify these, so I will just put them together until a better order comes up.&lt;/p&gt;
&lt;h3 id=&quot;fuzzy-finder-fzf&quot;&gt;Fuzzy finder: fzf &lt;a class=&quot;direct-link&quot; href=&quot;https://cmolina.dev/posts/2021/11/configure-terminal/#fuzzy-finder-fzf&quot;&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;script id=&quot;asciicast-yrkIY8pZ655d4xQ2KI2q01esV&quot; src=&quot;https://asciinema.org/a/yrkIY8pZ655d4xQ2KI2q01esV.js&quot; async=&quot;&quot; data-autoplay=&quot;1&quot; data-loop=&quot;1&quot;&gt;&lt;/script&gt;
&lt;p&gt;&lt;noscript&gt;&lt;img src=&quot;https://asciinema.org/a/yrkIY8pZ655d4xQ2KI2q01esV.svg&quot; alt=&quot;fzf demo&quot; /&gt;&lt;/noscript&gt;&lt;/p&gt;
&lt;p&gt;This utility is kind of hard to explain until you actually use it; in essence, it allows me to stop  hitting the &amp;quot;up&amp;quot; key for navigating my command history. I use it for autocompleting based on&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;my previous commands, by pressing &lt;kbd&gt;Ctrl&lt;/kbd&gt; + &lt;kbd&gt;R&lt;/kbd&gt;&lt;/li&gt;
&lt;li&gt;existing files and directories, by typing &lt;code&gt;the/path/I/remember/&lt;/code&gt; + &lt;code&gt;**&lt;/code&gt; + &lt;kbd&gt;TAB&lt;/kbd&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Get it from Homebrew, and read the docs at &lt;a href=&quot;https://github.com/junegunn/fzf&quot;&gt;https://github.com/junegunn/fzf&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;hyperfine-running-benchmarks&quot;&gt;hyperfine: running benchmarks &lt;a class=&quot;direct-link&quot; href=&quot;https://cmolina.dev/posts/2021/11/configure-terminal/#hyperfine-running-benchmarks&quot;&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;script id=&quot;asciicast-fwZEY9kp4VIcpGxsT8lw9jl6J&quot; src=&quot;https://asciinema.org/a/fwZEY9kp4VIcpGxsT8lw9jl6J.js&quot; async=&quot;&quot; data-autoplay=&quot;1&quot; data-loop=&quot;1&quot;&gt;&lt;/script&gt;
&lt;p&gt;&lt;noscript&gt;&lt;img src=&quot;https://asciinema.org/a/fwZEY9kp4VIcpGxsT8lw9jl6J.svg&quot; alt=&quot;hyperfine demo&quot; /&gt;&lt;/noscript&gt;&lt;/p&gt;
&lt;p&gt;In my spare time (i.e. when I am waiting for &lt;code&gt;npm install &amp;amp;&amp;amp; npm run build&lt;/code&gt; to complete) I&#39;d like to understand if I can make scripts to run faster: &lt;code&gt;hyperfine&lt;/code&gt; helps me measure how fast a proposed change compares to the initial state.&lt;/p&gt;
&lt;p&gt;(Fun fact: I once reduced the build time of a big NodeJS library in 30%, thanks &lt;code&gt;hyperfine&lt;/code&gt;!).&lt;/p&gt;
&lt;p&gt;Get it from Homebrew, and read the docs at &lt;a href=&quot;https://github.com/sharkdp/hyperfine&quot;&gt;https://github.com/sharkdp/hyperfine&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;version-managers&quot;&gt;Version managers &lt;a class=&quot;direct-link&quot; href=&quot;https://cmolina.dev/posts/2021/11/configure-terminal/#version-managers&quot;&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;If you work with multiple projects, and they all use the same dependency but with different versions, version manager can become quite handy. The ones that I&#39;ve used in the past are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;rvm&lt;/code&gt;: ruby version manager &lt;a href=&quot;https://rvm.io/rvm/install#installation&quot;&gt;https://rvm.io/rvm/install#installation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;nvm&lt;/code&gt;: node version manager &lt;a href=&quot;https://github.com/nvm-sh/nvm#installing-and-updating&quot;&gt;https://github.com/nvm-sh/nvm#installing-and-updating&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;wrapping-up&quot;&gt;Wrapping up &lt;a class=&quot;direct-link&quot; href=&quot;https://cmolina.dev/posts/2021/11/configure-terminal/#wrapping-up&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;These are the tools that I keep installing over and over in my Mac laptops. Do you have your favorites ones as well?&lt;/p&gt;

			
		</content>
	</entry>
	
	<entry>
		<title>Optimizing GitHub Actions: 7 Strategies for Faster and Cost-Effective CI pipelines</title>
		<link href="https://cmolina.dev/posts/2023/12/faster-and-cost-effective-github-actions/"/>
		<updated>2023-12-16T00:00:00Z</updated>
		<id>https://cmolina.dev/posts/2023/12/faster-and-cost-effective-github-actions/</id>
		<content type="html">
		  &lt;p&gt;From time to time, I need to change my focus from working on new features to ensure build times (and build costs) are reasonable.&lt;/p&gt;
&lt;p&gt;In this guide I will share some ideas on how I&#39;ve reduced the time and money spent in GitHub Actions, a CI managed service; these ideas may translate to other continuous integration services as well.&lt;/p&gt;
&lt;h2 id=&quot;measure-before-and-after-each-change&quot;&gt;Measure &lt;em&gt;before&lt;/em&gt; and &lt;em&gt;after&lt;/em&gt; each change &lt;a class=&quot;direct-link&quot; href=&quot;https://cmolina.dev/posts/2023/12/faster-and-cost-effective-github-actions/#measure-before-and-after-each-change&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This step is crucial when trying to optimize a process, we need to determine whether a change was beneficial, had no discernable impact, or had a performance hit compared to the &lt;em&gt;status quo&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Since GitHub Action runners are virtual machines over shared hosts, their performance change based on how busy the real machines are. For example I&#39;ve seen identical jobs to have different complete times that vary up to 10%, depending on the time and day of the week when these jobs are run.&lt;/p&gt;
&lt;p&gt;To rule out differences in performance due to these external factors:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I compare the times between a recently published PR, with the times against a job without these changes that &lt;strong&gt;run immediately after&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;I aim to keep only those PRs that make the build to run &lt;strong&gt;at least 10% faster&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now, let&#39;s explore the ideas that&#39;d worked for my team in the past.&lt;/p&gt;
&lt;h2 id=&quot;1-drop-unnecessary-work&quot;&gt;1. Drop unnecessary work &lt;a class=&quot;direct-link&quot; href=&quot;https://cmolina.dev/posts/2023/12/faster-and-cost-effective-github-actions/#1-drop-unnecessary-work&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This may seem obvious but sometimes it is easy to forget: the faster way to complete a job is to remove all its unnecessary steps.&lt;/p&gt;
&lt;p&gt;Take a look at a runner logs and see if there is any step that shouldn&#39;t be there. Things to look for:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;deprecated services&lt;/strong&gt; you are not using anymore&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;duplicated commands&lt;/strong&gt;. Sometimes a first CLI command will call a second CLI command, so you can drop one of those calls from the &lt;code&gt;*.yml&lt;/code&gt; definition&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;unnecessary commands&lt;/strong&gt;. I recently found out that in one of our apps I was &lt;em&gt;building the app&lt;/em&gt; before running its unit tests, an unnecessary step which was only making the build step slower.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;2-enable-concurrency-s-cancel-in-progress&quot;&gt;2. Enable concurrency&#39;s cancel-in-progress &lt;a class=&quot;direct-link&quot; href=&quot;https://cmolina.dev/posts/2023/12/faster-and-cost-effective-github-actions/#2-enable-concurrency-s-cancel-in-progress&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;What is the point of running a job once a new commit is in the HEAD of a branch, and a new job has just started? We are going to be spending money in a job that will be ignored, as it was superseded by the latest job.&lt;/p&gt;
&lt;p&gt;You can use the &lt;a href=&quot;https://docs.github.com/actions/using-workflows/workflow-syntax-for-github-actions#concurrency&quot;&gt;&lt;code&gt;concurrency&lt;/code&gt; property&lt;/a&gt; so every time anyone in your team pushes a new commit to a branch, &lt;em&gt;any existing running jobs related to that branch will be cancelled&lt;/em&gt;. For example:&lt;/p&gt;
&lt;pre class=&quot;language-yml&quot;&gt;&lt;code class=&quot;language-yml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;concurrency&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;group&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; $&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; github.ref &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;cancel-in-progress&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; $&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; github.ref_name &lt;span class=&quot;token tag&quot;&gt;!=&lt;/span&gt; &#39;main&#39; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The only exception here is for new commits added to the &lt;code&gt;main&lt;/code&gt; branch, as I&#39;d like to detect whether merging a PR breaks the build as soon as it happens.&lt;/p&gt;
&lt;h2 id=&quot;3-cache-dependencies&quot;&gt;3. Cache dependencies &lt;a class=&quot;direct-link&quot; href=&quot;https://cmolina.dev/posts/2023/12/faster-and-cost-effective-github-actions/#3-cache-dependencies&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Your program will probably use dependencies, and installing them each time from an empty cache can be time-consuming. And when you use CI, you will be installing the same dependencies over and over again; so there is an opportunity to keep a copy of your dependencies across jobs to reduce build times.&lt;/p&gt;
&lt;p&gt;For this reason popular languages actions provide some &lt;em&gt;caching&lt;/em&gt; feature, to save and reuse these dependencies across runs.&lt;/p&gt;
&lt;p&gt;Here there are a couple of examples of actions with caching enabled, for both ruby gems and npm packages:&lt;/p&gt;
&lt;pre class=&quot;language-yml&quot;&gt;&lt;code class=&quot;language-yml&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;uses&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; ruby/setup&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;ruby@v1&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;with&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;bundler-cache&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;true&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;uses&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; actions/setup&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;node@v3&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;with&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;node-version-file&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; package.json&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;cache&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; yarn&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Sometimes there are dependencies which are not automatically stored by these actions. For that case you can leverage the &lt;code&gt;actions/cache&lt;/code&gt; action, and manually cache and restore these dependencies yourself.&lt;/p&gt;
&lt;p&gt;Here there is an example for caching Playwright&#39;s dependencies and browsers:&lt;/p&gt;
&lt;pre class=&quot;language-yml&quot;&gt;&lt;code class=&quot;language-yml&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# caching Playwright&#39;s dependencies and browsers; notice it has 3 steps&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Save the installed Playwright version&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; echo &quot;PLAYWRIGHT_VERSION=$(yarn list &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;pattern=&quot;@playwright/test&quot; &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;json &lt;span class=&quot;token punctuation&quot;&gt;|&lt;/span&gt; jq &#39;.data.trees&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;.name&#39; &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;r &lt;span class=&quot;token punctuation&quot;&gt;|&lt;/span&gt; sed &#39;s/.&lt;span class=&quot;token important&quot;&gt;*@//&#39;)&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt; $GITHUB_ENV&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Restore Playwright dependencies and browsers from the cache&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;uses&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; actions/cache@v3&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; playwright&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;cache&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;with&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; ~/.cache/ms&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;playwright&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; $&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; runner.os &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;playwright&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;$&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; env.PLAYWRIGHT_VERSION &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;restore-keys&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; $&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; runner.os &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;playwright&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Download Playwright dependencies and browsers&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; steps.playwright&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;cache.outputs.cache&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;hit &lt;span class=&quot;token tag&quot;&gt;!=&lt;/span&gt; &#39;true&#39;&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; yarn playwright install &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;with&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;deps chromium&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;4-enable-parallelism-in-your-framework&quot;&gt;4. Enable parallelism in your framework &lt;a class=&quot;direct-link&quot; href=&quot;https://cmolina.dev/posts/2023/12/faster-and-cost-effective-github-actions/#4-enable-parallelism-in-your-framework&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The runners provided by GitHub Actions can run multiple threads; however there are times the frameworks may fail to detect how much parallelization can be done. The larger your project, the more tests you will have, and the more your project can take advantage of splitting the work across all the threads your runner supports, reducing your build times.&lt;/p&gt;
&lt;p&gt;In the following example, I am setting the &lt;code&gt;PARALLEL_WORKERS&lt;/code&gt; env var so &lt;code&gt;minitest&lt;/code&gt; knows how many workers it can actually use:&lt;/p&gt;
&lt;pre class=&quot;language-yml&quot;&gt;&lt;code class=&quot;language-yml&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Set parallel workers env variable&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; echo &quot;PARALLEL_WORKERS=$(nproc)&quot; &lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt; $GITHUB_ENV&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Run Ruby and Rails tests&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;env&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;RAILS_ENV&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; test&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; bundle exec rails test&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;5-optimize-dependabot&quot;&gt;5. Optimize Dependabot &lt;a class=&quot;direct-link&quot; href=&quot;https://cmolina.dev/posts/2023/12/faster-and-cost-effective-github-actions/#5-optimize-dependabot&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Here I&#39;ve found 2 tricks that have saved me money:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Enable &lt;a href=&quot;https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file#groups&quot;&gt;&lt;code&gt;groups&lt;/code&gt;&lt;/a&gt;, to reduce the number of open PRs for each day&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;For example, we can have a single PR that bumps the versions of all &lt;code&gt;bundler&lt;/code&gt;-related dependencies at the same time, except the &lt;code&gt;rubocop&lt;/code&gt; ones, which will be updated in a separate PR:&lt;/p&gt;
&lt;div class=&quot;code-filename&quot;&gt;.github/dependabot.yml&lt;/div&gt;
&lt;pre class=&quot;language-yml&quot;&gt;&lt;code class=&quot;language-yml&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;package-ecosystem&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;bundler&quot;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;groups&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;development-dependencies&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token key atrule&quot;&gt;dependency-type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;development&quot;&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token key atrule&quot;&gt;exclude-patterns&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;rubocop*&quot;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;rubocop&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token key atrule&quot;&gt;patterns&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;rubocop*&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Beware: the grouping will have a bigger impact when dependencies are updated once a week; for daily updates groups doesn&#39;t make a lot of sense.&lt;/p&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;Use &lt;code&gt;commit-message&lt;/code&gt; for customizing the commit message &lt;strong&gt;and its PR title&lt;/strong&gt;, so I can skip other services&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;I configured my dependabot PRs to be automatically merged once all jobs are passing. And since there is no human involved in these PRs, I want to avoid triggering deployments for manually testing the changes.&lt;/p&gt;
&lt;p&gt;For example, I can avoid running &lt;a href=&quot;https://render.com/docs/preview-environments&quot;&gt;Render.com&#39;s preview environments&lt;/a&gt;, which can become particularly expensive, by adding a particular prefix to the PR title:&lt;/p&gt;
&lt;div class=&quot;code-filename&quot;&gt;.github/dependabot.yml&lt;/div&gt;
&lt;pre class=&quot;language-yml&quot;&gt;&lt;code class=&quot;language-yml&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;package-ecosystem&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;bundler&quot;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;commit-message&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;prefix&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;[skip render]&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And with less preview enviroments, the smaller the &lt;a href=&quot;http://render.com/&quot;&gt;Render.com&lt;/a&gt;&#39;s bill 😁&lt;/p&gt;
&lt;h2 id=&quot;6-use-larger-runners&quot;&gt;6. Use larger runners &lt;a class=&quot;direct-link&quot; href=&quot;https://cmolina.dev/posts/2023/12/faster-and-cost-effective-github-actions/#6-use-larger-runners&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The default runners provided by GitHub are potatoes connected to the internet. If you want to use a modern browser to run system tests you may run out of memory, the tests may run very slowly, or probably both.&lt;/p&gt;
&lt;p&gt;The easiest solution is to have faster builds is to opt-in to better runners. You can use &lt;a href=&quot;https://docs.github.com/en/actions/using-github-hosted-runners/about-larger-runners&quot;&gt;the larger runners provided by GitHub&lt;/a&gt;, which you first need to enable for your org, and then set the &lt;code&gt;run-on&lt;/code&gt; property, for example:&lt;/p&gt;
&lt;pre class=&quot;language-yml&quot;&gt;&lt;code class=&quot;language-yml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;jobs&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;system-tests&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;runs-on&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; ubuntu&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;latest&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;16&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;cores&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;However, &lt;strong&gt;using these hosts can become pretty expensive, very quickly&lt;/strong&gt;. I saw my GitHub bill to grow up to 3 times after a few months using larger runners, so be careful when using this setting and keep track of your monthly charges.&lt;/p&gt;
&lt;p&gt;Instead, I would recommend to use larger runners from a third party provider. There are services like &lt;a href=&quot;https://www.warpbuild.com/&quot;&gt;Warp Build&lt;/a&gt; and &lt;a href=&quot;https://gitrunners.com/&quot;&gt;GitRunners&lt;/a&gt; that allows you to enjoy faster machines at a fraction of the cost when compared to GitHub.&lt;/p&gt;
&lt;p&gt;Using larger runners will make your jobs be faster and more expensive. In this case I think it is cheaper than having developers waiting for their changes to go live.&lt;/p&gt;
&lt;h2 id=&quot;7-split-the-work-with-multiple-runners&quot;&gt;7. Split the work with multiple runners &lt;a class=&quot;direct-link&quot; href=&quot;https://cmolina.dev/posts/2023/12/faster-and-cost-effective-github-actions/#7-split-the-work-with-multiple-runners&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Let&#39;s say you have a &lt;code&gt;N&lt;/code&gt; system tests. If you run them all in a single runner, and the last test fails, you will still need to wait for all &lt;code&gt;N&lt;/code&gt; tests to complete.&lt;/p&gt;
&lt;p&gt;What if we split the load, let&#39;s say between 5 hosts?&lt;/p&gt;
&lt;p&gt;So now, if the last test fails, we will know it in about 1/5 of the original time, making it 80% faster!&lt;/p&gt;
&lt;p&gt;We can leverage the &lt;code&gt;strategy&lt;/code&gt; and &lt;code&gt;matrix&lt;/code&gt; properties, for example we can split the following Playwright tests by setting the &lt;a href=&quot;https://playwright.dev/docs/test-sharding&quot;&gt;shard option&lt;/a&gt;:&lt;/p&gt;
&lt;pre class=&quot;language-yml&quot;&gt;&lt;code class=&quot;language-yml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;system-tests&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; System tests&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;strategy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;fail-fast&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;false&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;matrix&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token key atrule&quot;&gt;shard&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;env&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token key atrule&quot;&gt;SHARD&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; $&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; matrix.shard &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;/$&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; strategy.job&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;total &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# for example: 1/5, 2/2, ..., 5/5&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token key atrule&quot;&gt;steps&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;# other setup steps...&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Run Playwright system tests&lt;br /&gt;      &lt;span class=&quot;token key atrule&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; yarn playwright test &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;project=chromium &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;shard=$SHARD&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Unfortunately, as of today, rails doesn&#39;t support sharding in their tests. &lt;a href=&quot;https://gist.github.com/cmolina/a50f54848529a55965fb2d0eec64a1fe&quot;&gt;I wrote a small rake task&lt;/a&gt; that is equivalent to running rails&#39; system tests in shards, like Playwright.&lt;/p&gt;
&lt;p&gt;If you want some extra savings, you can toggle &lt;code&gt;fail-fast: true&lt;/code&gt; so you cancel other jobs from the matrix at the first error; however I prefer to keep it off so I know all the system tests that needs to be fixed.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion &lt;a class=&quot;direct-link&quot; href=&quot;https://cmolina.dev/posts/2023/12/faster-and-cost-effective-github-actions/#conclusion&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Well, here are 7 ideas on how to have faster and cheaper CI with GitHub Actions. I will probably find some new ideas in the future, but for now I am enjoying the faster integrations.&lt;/p&gt;

			
		</content>
	</entry>
	
	<entry>
		<title>Rock Your Code with AC/DC: Acceptance Criteria Designed Coding</title>
		<link href="https://cmolina.dev/posts/2024/05/rock-with-acdc/"/>
		<updated>2024-05-22T00:00:00Z</updated>
		<id>https://cmolina.dev/posts/2024/05/rock-with-acdc/</id>
		<content type="html">
		  &lt;p&gt;Welcome to the world of AC/DC, where coding meets rock &#39;n&#39; roll! No, we’re not talking about shredding guitars or belting out high notes. This &lt;abbr title=&quot;Acceptance Criteria Designed Coding&quot;&gt;AC/DC&lt;/abbr&gt; stands for &lt;em&gt;Acceptance Criteria Designed Coding&lt;/em&gt;, a new technique I’ve been crafting for the past few years. It’s a nod to the legendary band, and a cheeky jab at &lt;a href=&quot;https://martinfowler.com/bliki/TestDrivenDevelopment.html&quot;&gt;TDD&lt;/a&gt; fans. Buckle up and get ready to rock your coding workflow!&lt;/p&gt;
&lt;h2 id=&quot;the-power-chords-of-ac-dc&quot;&gt;The Power Chords of AC/DC &lt;a class=&quot;direct-link&quot; href=&quot;https://cmolina.dev/posts/2024/05/rock-with-acdc/#the-power-chords-of-ac-dc&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Let’s break down the process and get you rocking.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Grab an Acceptance Criteria (AC) from a Story&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;List all its cases&lt;/strong&gt;. Create a playlist of &lt;em&gt;scenarios&lt;/em&gt;. Make sure you keep this list up-to-date as you learn and discover new edge cases&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Pick a case, and write it in code following these rules:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Design the ideal signature&lt;/strong&gt;. Make sure to use the same language of the AC&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Asserting &lt;em&gt;behavior&lt;/em&gt;, never &lt;em&gt;implementation&lt;/em&gt;&lt;/strong&gt;: We’re here to rock the stage, not worry about the backstage setup&lt;/li&gt;
&lt;li&gt;Use &lt;strong&gt;Arrange, Act, Assert&lt;/strong&gt;: Your three-step dance routine.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Make sure the new AC’s case is failing:&lt;/strong&gt; If it’s not failing, it’s not rocking hard enough.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Write the minimum amount of code&lt;/strong&gt; to make the AC’s case pass: Think minimalistic, like a raw guitar riff.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Optional refactor:&lt;/strong&gt; Clean up your code and make it smooth.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Confirm all AC&#39;s cases are passing:&lt;/strong&gt; Like hitting are the right notes!&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;If there are still cases unimplement, go back to step 3&lt;/strong&gt;. There is more rocking to do&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Next AC, Please:&lt;/strong&gt; Once you’re done, grab the next AC from the story and start over. It is time for a new hit&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src=&quot;https://cmolina.dev/img/2024/05/acdc-diagram.svg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;h2 id=&quot;why-use-ac-dc&quot;&gt;Why Use AC/DC? &lt;a class=&quot;direct-link&quot; href=&quot;https://cmolina.dev/posts/2024/05/rock-with-acdc/#why-use-ac-dc&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Following AC/DC ensures you address all the ACs from a story. If they ever break, you’ll be notified immediately – no more surprise bugs halfway through your concert. This technique has allowed me to move fast in projects while maintaining high code quality.&lt;/p&gt;
&lt;h1 id=&quot;let-s-rock-an-example&quot;&gt;Let&#39;s Rock an Example &lt;a class=&quot;direct-link&quot; href=&quot;https://cmolina.dev/posts/2024/05/rock-with-acdc/#let-s-rock-an-example&quot;&gt;¶&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Let’s say we’re grabbing a story for calculating the total price of items in a cart, including tax, in a JavaScript app. Here’s how we’d rock this with AC/DC.&lt;/p&gt;
&lt;h2 id=&quot;step-by-step&quot;&gt;Step-by-Step &lt;a class=&quot;direct-link&quot; href=&quot;https://cmolina.dev/posts/2024/05/rock-with-acdc/#step-by-step&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Grab an AC from a story: Calculate the total price of items in a cart, including a fixed tax rate of 10%.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;List all its cases:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;An empty cart should return 0&lt;/li&gt;
&lt;li&gt;A cart with one item of price 100 should return 110 (including tax)&lt;/li&gt;
&lt;li&gt;A cart with multiple items should sum up all prices and add tax&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Pick a case: Let’s start with an empty cart.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&quot;code-filename&quot;&gt;calculateTotalPrice.test.js&lt;/div&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; describe&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; it&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; expect &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;vitest&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; calculateTotalPrice &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;./calculateTotalPrice&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;should return 0 for an empty cart&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token comment&quot;&gt;// Arrange&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; cart &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span class=&quot;token comment&quot;&gt;// Act&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;calculateTotalPrice&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;cart&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span class=&quot;token comment&quot;&gt;// Assert&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token function&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;result&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toBe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;ol start=&quot;4&quot;&gt;
&lt;li&gt;Make sure the new AC’s case is failing: Run the test to see it fail.&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;vitest run&lt;/code&gt;&lt;/pre&gt;
&lt;ol start=&quot;5&quot;&gt;
&lt;li&gt;Write the minimum amount of code to make the AC’s case pass:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&quot;code-filename&quot;&gt;calculateTotalPrice.test.js&lt;/div&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;calculateTotalPrice&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;cart&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// minimum code to pass the test&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;ol start=&quot;6&quot;&gt;
&lt;li&gt;
&lt;p&gt;Optionally refactor: No need yet.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Confirm all AC’s cases are passing: Run the test again.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;vitest run&lt;/code&gt;&lt;/pre&gt;
&lt;ol start=&quot;8&quot;&gt;
&lt;li&gt;If there are still cases unimplemented, go back to step 3: Next case!&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&quot;code-filename&quot;&gt;calculateTotalPrice.test.js&lt;/div&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token function&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;should return 110 for a cart with one item priced at 100&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; cart &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; price&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;100&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;calculateTotalPrice&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;cart&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span class=&quot;token function&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;result&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toBe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;110&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Run the test to see it fail, then write the minimal code:&lt;/p&gt;
&lt;div class=&quot;code-filename&quot;&gt;calculateTotalPrice.js&lt;/div&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;calculateTotalPrice&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;cart&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;cart&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; cart&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;price &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1.1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// minimal code to pass the second test&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Once you write the last case, you may end up with a function like this:&lt;/p&gt;
&lt;div class=&quot;code-filename&quot;&gt;calculateTotalPrice.js&lt;/div&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;calculateTotalPrice&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;cart&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;cart&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; total &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; cart&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;reduce&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;sum&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; item&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; sum &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; item&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;price&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; total &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1.1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;ol start=&quot;6&quot;&gt;
&lt;li&gt;Optional refactor. We can replace the 1.1 &lt;em&gt;magic number&lt;/em&gt; into a well-named constant:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&quot;code-filename&quot;&gt;calculateTotalPrice.js&lt;/div&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;TAX_RATE&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1.1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;calculateTotalPrice&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;cart&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;cart&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; total &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; cart&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;reduce&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;sum&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; item&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; sum &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; item&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;price&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; total &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;TAX_RATE&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;ol start=&quot;7&quot;&gt;
&lt;li&gt;Confirm all tests are passing, and move on to the next AC with step 9.&lt;/li&gt;
&lt;/ol&gt;
&lt;h1 id=&quot;why-ac-dc-rocks&quot;&gt;Why AC/DC Rocks &lt;a class=&quot;direct-link&quot; href=&quot;https://cmolina.dev/posts/2024/05/rock-with-acdc/#why-ac-dc-rocks&quot;&gt;¶&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Following AC/DC ensures you cover all the acceptance criteria in a user story, providing a safety net that alerts you if any criteria ever break. This technique lets you move fast in projects while maintaining stellar code quality. It’s like having your own coding concert where every function hits the perfect note.&lt;/p&gt;
&lt;p&gt;So, turn up the volume on your coding skills and give AC/DC a spin. You might just find yourself rocking out more efficient, reliable, and downright awesome code. Rock on! 🎸&lt;/p&gt;

			
		</content>
	</entry>
</feed>
