<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Run, Code & Learn]]></title><description><![CDATA[Google Developer Expert, GitKraken Ambassador, Former Microsoft MVP, Senior Software Developer at NearForm and javascript and typescript enthusiastic.]]></description><link>https://blog.delpuppo.net</link><generator>RSS for Node</generator><lastBuildDate>Wed, 22 Apr 2026 06:04:02 GMT</lastBuildDate><atom:link href="https://blog.delpuppo.net/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Take control of your job with GitLens Launchpad]]></title><description><![CDATA[As a developer, you have to take control of your projects every day. Whether it is a company repository, an open source project you maintain or collaborate on, or a simple pet project.
Gaining control over your projects often depends on the platform ...]]></description><link>https://blog.delpuppo.net/take-control-of-your-job-with-gitlens-launchpad</link><guid isPermaLink="true">https://blog.delpuppo.net/take-control-of-your-job-with-gitlens-launchpad</guid><category><![CDATA[Developer Tools]]></category><category><![CDATA[DeveloperExperience]]></category><category><![CDATA[gitkraken]]></category><dc:creator><![CDATA[Luca Del Puppo]]></dc:creator><pubDate>Mon, 22 Dec 2025 19:57:21 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1766240972674/2ffb61ec-f7e3-4ca3-b4d5-9718083e3628.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>As a developer, you have to take control of your projects every day. Whether it is a company repository, an open source project you maintain or collaborate on, or a simple pet project.</p>
<p>Gaining control over your projects often depends on the platform you're working with. While there are many options available, such as <a target="_blank" href="http://atlassian.com/">Atlassian</a> and <a target="_blank" href="https://gitlab.com">GitLab</a>, today I will focus on using <a target="_blank" href="https://github.com/">GitHub</a> as the platform of choice. Let me guide you through how you can effectively manage your projects on <a target="_blank" href="https://github.com/">GitHub</a>.</p>
<p>I’ll talk about the <a target="_blank" href="https://github.com/">GitHub</a> one because that is where I’m working on.</p>
<p>For me, checking the status of my PRs is essential in my daily work. On average, I spend about one or two hours a day tracking down failing CI checks and keeping my PRs in sync with the main branch, or reviewing other PRs.</p>
<p>To do that, I used to use the <a target="_blank" href="https://github.com/">GitHub</a> website on <a target="_blank" href="https://github.com/pulls">my PRs page</a>. This page is good; you can find all your PRs, including those where your teammates are requesting a review. You can check whether your PR has reviews and whether the CI passes.</p>
<p><img src="https://codahosted.io/docs/8hYN1hdop_/blobs/bl-JiD5d09WQB/d4b8bea2c1ea121fb163fe6b607c16d595c0be73fb43e43ab49c523e390b3ac260a2bee935b6676d5242325eb8ebf57678f22ade29921a992cec0232809018e3fb8aaa02b3f192081a27ecf265c779ec64555a75da85aae07ed9960ba853b944fde50cb6" alt="github.com_pulls.png" /></p>
<p>Here you can see my PRs at this specific moment.</p>
<p>As you can see, you can immediately receive information about the PRs, the number of comments, and more.</p>
<p>I used this page for a while because it is a perfect way to check all the work across many repositories, but it has a small problem: to check the page, I have to switch between <a target="_blank" href="https://code.visualstudio.com/">VSCode</a> and the browser during my job. This constant switching might seem trivial, but research suggests it takes an average of 23 seconds to return to a productive state after such a context switch. In the fast-paced developer environment, these seconds add up, potentially impacting overall efficiency and output.</p>
<p>So, I decided to search for another solution that would let me have the same information across the projects without leaving my <a target="_blank" href="https://code.visualstudio.com/">VSCode</a> instance.</p>
<h2 id="heading-the-first-useful-extensions-to-the-migration">The first useful extensions to the migration</h2>
<p><a target="_blank" href="https://marketplace.visualstudio.com/items?itemName=GitHub.vscode-pull-request-github">GitHub Pull Requests</a> was the first extension I started to test. This extension enables checking all PRs in the current repository I’m working on. I can see my open PRs and my teammates' open PRs. From a <a target="_blank" href="https://code.visualstudio.com/">VSCode</a> panel, I can check the status of a PR or review another one.<br />This extension enables us to open a PR directly from <a target="_blank" href="https://code.visualstudio.com/">VSCode</a> without using the <a target="_blank" href="https://github.com/">GitHub</a> website, reducing the need to switch context between the editor and the <a target="_blank" href="https://github.com/">GitHub</a> website.<br />Here is a picture of the extension</p>
<p><img src="https://codahosted.io/docs/8hYN1hdop_/blobs/bl-T4QCMINucN/6e491a00314822652cffc10a7e73d9583abe6f38d526b4cbb22617dbd85ad8479a67e80fcfe0eb3839181138d21b660f76b81d14602c2c25784ae0bead254f302defb9c5df3dd183ffaf4902d455a2a4e350222c5b8967a63cd2cde77badfb446c6bef86" alt="Screenshot 2025-12-20 at 13.56.40.png" /></p>
<p>As you can see, in the left panel, we can control PRs and Issues. By clicking the PR, we can view its home page. By clicking the arrow icon that appears when you hover over the PR, you can go to the Review mode and add comments or suggestions to that PR.</p>
<p>That extension has improved my DX experience, especially in PR creation and review, but, as you can see, it works only on the open repository, which is a limitation, since I cannot see if in other projects something or someone is blocked by my work, or it’s waiting for a review or something else.</p>
<h2 id="heading-the-final-solution">The Final Solution</h2>
<p>While browsing the web, I came across a feature of <a target="_blank" href="https://www.gitkraken.com/">GitKraken</a> called <a target="_blank" href="https://www.gitkraken.com/features/launchpad">Launchpad</a>. This feature enables us to get a big-picture view of all issues and PRs where we are the creator or a follower. If you don’t know <a target="_blank" href="https://www.gitkraken.com/">GitKraken</a>, it is a Git client with an awesome UI for managing your repositories. You can use it as a <a target="_blank" href="https://www.gitkraken.com/git-client?_gl=1*1yb8ynx*_up*MQ..*_ga*MTM4MjU2MTEwMS4xNzY2MjM2Mjc3*_ga_TTGBQHQ5E4*czE3NjYyMzYyNzYkbzEkZzAkdDE3NjYyMzYyNzYkajYwJGwxJGgxNjcyOTAyNTQ3">desktop app</a>, <a target="_blank" href="https://gitkraken.dev/">website</a>, editor extension (<a target="_blank" href="https://www.gitkraken.com/gitlens?_gl=1*w5a9a6*_up*MQ..*_ga*MTEyMDYwODM3LjE3NjYyMzYzMTQ.*_ga_TTGBQHQ5E4*czE3NjYyMzYzMTMkbzEkZzAkdDE3NjYyMzYzMTMkajYwJGwxJGgyMDQ0NjUzMjY0">GitLens</a>), or the <a target="_blank" href="https://www.gitkraken.com/cli?_gl=1*1ltt9q5*_up*MQ..*_ga*MTEyMDYwODM3LjE3NjYyMzYzMTQ.*_ga_TTGBQHQ5E4*czE3NjYyMzYzMTMkbzEkZzEkdDE3NjYyMzY2ODgkajYwJGwxJGgyMDQ0NjUzMjY0">CLI</a>. They have also released an <a target="_blank" href="https://www.gitkraken.com/mcp?_gl=1*1p7bqfc*_up*MQ..*_ga*MTEyMDYwODM3LjE3NjYyMzYzMTQ.*_ga_TTGBQHQ5E4*czE3NjYyMzYzMTMkbzEkZzEkdDE3NjYyMzY3MjAkajI4JGwxJGgyMDQ0NjUzMjY0">MCP server</a> in the last period to manage your repository through an LLM.<br />As you can imagine, I use the <a target="_blank" href="https://www.gitkraken.com/gitlens">GitLens</a> extension, which has a panel that lets me see everything across my repositories.<br /><em>Spoiler: I use it with</em> <a target="_blank" href="https://github.com/"><em>GitHub</em></a><em>, but you can also use it with</em> <a target="_blank" href="https://bitbucket.org/"><em>Bitbucket</em></a> <em>and</em> <a target="_blank" href="https://gitlab.com/"><em>GitLab</em></a><em>. It can also combine data across different platforms.</em></p>
<p><img src="https://codahosted.io/docs/8hYN1hdop_/blobs/bl-_KfjdjSErQ/c44bf0505646d78c9b2da6dd8ab3d6aa525769ee5b66663dbbc93c2a52b243063a1eb5d19efb571eee4fa03eda39ac7df8f47006ce9dc8809b7f6b57a1d4c2e1d3abb20325a242ac8522bd138214b98e2ab58795725a881618c12cf342e04005848a022f" alt="Screenshot 2025-12-20 at 14.25.37.png" /></p>
<p>In this panel, there are different groups where you can find your PRs that meet that status. If you click the PR, you will see a pop-up that lets you get more info or jump into the repository if you have already set it up on your machine.</p>
<p><img src="https://codahosted.io/docs/8hYN1hdop_/blobs/bl-2aXRO3UPae/e25890539743eaef871ba9b38ef8e09040ddc3f7b46c57f605228146bede5e40bf3ee39aacd51545d4f6402f58145b52df1e1585e2259cfcf8b7add935e111f94f5f1c2674fe718510e22f11715370f8f6d04ba41e0367f60e93b0bd9f56d0fc75be131a" alt="Screenshot 2025-12-20 at 14.39.33.png" /></p>
<p>As you can see, just using these two extensions, I reduced the number of switches between my lovely <a target="_blank" href="https://code.visualstudio.com/">VSCode</a> and the <a target="_blank" href="https://github.com/">GitHub</a> website. In my editor, I already have control over all my repositories, and with the correct panel, I can do most of my work directly in the editor.</p>
<p>Before closing, I’d like to give you another extension that reduces the need to switch between the editor and the <a target="_blank" href="https://github.com/">GitHub</a> website. This extension is the <a target="_blank" href="https://marketplace.visualstudio.com/items?itemName=GitHub.vscode-github-actions">GitHub Actions</a> one. This extension lets you check the status of actions directly in the editor, without jumping to <a target="_blank" href="https://github.com/">GitHub</a> to search for them.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>It’s time to wrap up this article.<br />At first, I showed how I used to check my current work across projects on <a target="_blank" href="https://github.com/">GitHub</a>, but eventually it became a pain point because switching between the editor and the browser was annoying.<br />Then I moved to the <a target="_blank" href="https://marketplace.visualstudio.com/items?itemName=GitHub.vscode-pull-request-github">GitHub Pull Requests</a> extension, which enables me to open, review, and check PRs and Issues in the current open repository.<br />Lastly, I talked about the <a target="_blank" href="https://www.gitkraken.com/gitlens">GitLens</a> <a target="_blank" href="https://www.gitkraken.com/features/launchpad">Launchpad,</a> which, through a panel in the editor, provides a big-picture view of all the PRs across the repositories I’m working on and helps me reduce switching between the editor and <a target="_blank" href="https://github.com/">GitHub</a> during my daily work.</p>
<p><em>If you want to use the</em> <a target="_blank" href="https://www.gitkraken.com/gitlens"><em>GitLens</em></a> <em>Launchpad, it is a PRO feature that requires a valid</em> <a target="_blank" href="https://www.gitkraken.com/"><em>GitKraken</em></a> <em>license. To buy one, check this</em> <a target="_blank" href="https://gitkraken.cello.so/I4dkhuQcpJN"><em>link</em></a><em>.</em></p>
<p>That’s it for this article. I hope this feature can also improve your daily DX, and see you in the following articles.</p>
<p>Bye bye 👋</p>
]]></content:encoded></item><item><title><![CDATA[The Mood Mirror App]]></title><description><![CDATA[Just a week ago, Google launched Antigravity, and why not give it a try and share my experience? And here I am for this.
In this article, I'll talk about my first experience with Antigravity and how I built a small web app called The Mood Mirror. Thi...]]></description><link>https://blog.delpuppo.net/the-mood-mirror-app</link><guid isPermaLink="true">https://blog.delpuppo.net/the-mood-mirror-app</guid><category><![CDATA[AI]]></category><category><![CDATA[Google Antigravity]]></category><category><![CDATA[gemini]]></category><category><![CDATA[vibe coding]]></category><dc:creator><![CDATA[Luca Del Puppo]]></dc:creator><pubDate>Wed, 03 Dec 2025 16:37:47 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1764457549492/2561887e-4fd6-49b3-8a32-a1dc48a6c62d.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Just a week ago, Google launched <a target="_blank" href="https://antigravity.google/">Antigravity</a>, and why not give it a try and share my experience? And here I am for this.</p>
<p>In this article, I'll talk about my first experience with Antigravity and how I built a small web app called <strong>The Mood Mirror</strong>. This app emulates an artist who can convert your mood into abstract images or videos.</p>
<p>Spoiler: this app uses <a target="_blank" href="https://deepmind.google/models/gemini/">Gemini 3</a>, <a target="_blank" href="https://gemini.google/overview/image-generation/">Nano Banana Pro</a> and <a target="_blank" href="https://gemini.google/overview/video-generation/">Veo</a>, but I'll talk about them in a future article.</p>
<h2 id="heading-antigravity-intro">Antigravity Intro</h2>
<p>Let's start with a small presentation about Antigravity.</p>
<p>Google Antigravity is an Agentic IDE. It is a fork of VSCode with a dedicated agent section that features models such as Gemini, Claude, and GPT.</p>
<p>This last part is what makes Antigravity different from VSCode or Cursor; this section is built and maintained by Google. Yes, the experiences are common, but how this Agent section is integrated into the IDE is what differentiates it from the others, and this is where all the IDE teams are working to improve their users' DX.</p>
<p>For more info about Google Antigravity, you can check its website <a target="_blank" href="https://antigravity.google/">here</a>.</p>
<h2 id="heading-the-mood-mirror-setup">"The Mood Mirror" Setup</h2>
<p>To test the tool's full power, I decided to build the application almost entirely in "Vibe Coding". To that end, I began by setting up the project and wrote a prompt outlining my intention and what I hoped to achieve.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1764425511989/bd7ac121-da29-417c-90c2-4a7dadf10459.png" alt="Antigravity Screen" class="image--center mx-auto" /></p>
<p>In this picture, you can see what Antigravity looks like, and as you can imagine, in the chat, you can prompt our intention.</p>
<p>For my application, I entered this prompt.</p>
<p><strong>Role:</strong> You are a Senior Software Engineer Agent.</p>
<p><strong>Project:</strong> Build a responsive web application called <strong>"Mood Mirror"</strong>.</p>
<p><strong>Stack:</strong> React, Tailwind CSS, and the Gemini 3 SDK.</p>
<p><strong>Core Functionality:</strong></p>
<ol>
<li><p><strong>Input:</strong> Create a clean, minimalist text area where the user enters how they feel (e.g., "I am anxious about my deadline").</p>
</li>
<li><p><strong>The "Director" Logic (Gemini 3):</strong> When the user submits, send the text to Gemini 3.</p>
<ul>
<li><p>Analyse the <strong>Sentiment Score</strong> (0 to +1.0).</p>
</li>
<li><p>Extract an <strong>Emotional Colour Palette</strong> (e.g., "Stormy Grey and Electric Blue").</p>
</li>
<li><p>Generate a <strong>Creative Prompt</strong> for an abstract art piece based on that emotion.</p>
</li>
</ul>
</li>
<li><p><strong>The "Artist" Execution (Nano Banana):</strong></p>
<ul>
<li><p>Pass the <em>Creative Prompt</em> to the Nano Banana Pro API.</p>
</li>
<li><p><strong>Conditional Logic:</strong> If the Sentiment Score is extreme (above 0.8 or below -0.8), request a <strong>5-second looping Video (MP4)</strong>. Otherwise, request a <strong>High-Res Image (PNG)</strong>.</p>
</li>
</ul>
</li>
<li><p><strong>Dynamic UI:</strong> Update the app's background gradient instantly to match the <em>Emotional Colour Palette</em> returned by Gemini while the image generates.</p>
</li>
</ol>
<p><strong>Execution Plan:</strong></p>
<ul>
<li><p>Scaffold the project.</p>
</li>
<li><p>Write the SentimentService using the Gemini 3 logic.</p>
</li>
<li><p>Implement the Nano Banana API hook.</p>
</li>
<li><p>Deploy to preview.</p>
</li>
</ul>
<p>The result of this prompt was a plan of action for Antigravity to implement my request. I got this result because I selected "planning" in the bottom-left drop-down. If you decide to go with the fast option, Antigravity doesn't show the plan and immediately develops it.</p>
<p>Btw, I chose the planning options so that I can check and comment on this plan directly in the IDE.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1764425555307/82f0e260-e9ea-44ac-bdd6-3cc910402b28.png" alt class="image--center mx-auto" /></p>
<p>In the image above, you can see an example of the plan I received. As you can see, you can either accept it or review it, and then ask Antigravity to check your comments and review the plan.</p>
<p>The prompt and its plan are the result of this <a target="_blank" href="https://github.com/Puppo/the-mood-mirror/commit/e5a2784b77c93014a9cb36ecd70c94a2ef8e4a13">commit</a>.</p>
<p><strong>What went wrong? 😑</strong></p>
<p>The setup has gone smoothly and pretty well, but I ran into an issue: Antigravity generated a JavaScript application rather than a TypeScript one. Not a big deal. Later, I asked it to review the project in JavaScript and TypeScript, and it converted it without any issues. <a target="_blank" href="https://github.com/Puppo/the-mood-mirror/commit/66ba677e104cca6c1c09de4d339e1e6e9cae4c77">Here</a> you can see the result.<br />And lastly, it generated two files, one for the Sentiment discovery and the other for the image generation, but it created a sort of mock service without.<br />I didn’t iterate again to fix them, but I’ve worked on them later.</p>
<h2 id="heading-commit-linting-into-the-project">Commit linting into the project</h2>
<p>The second test I did was about setting up a development tool to verify the commit messages. I like to use commitlint and conventional commits for my project, so my second test was adding the setup for these tools.<br />I opened a new chat, and I entered this prompt.</p>
<p><em>I want to add commitlint and conventional-commit to this project. Can you set it up?</em></p>
<p>I was concerned that the prompt wasn’t particular, but I did it to see what Antigravity produces and how good the results are.</p>
<p>I ran that prompt in “fast” mode, and the first result was pretty good. It installs and sets up <code>@commitlint/cli</code> and <code>@commitlint/config-conventional</code> and after that, it added <code>husky</code> to validate the commit message in the pre-commit hook. I’m not a <code>husky</code> fan, I prefer <code>lefthook</code>. So after this first iteration, I asked Antigravity to replace <code>husky</code> with <code>lefthook</code>. The result I got worked, but it wasn’t the best solution ever. I decided not to reiterate this time, to leave it in the repo and also show what an Agentic IDE can generate when we don’t check its results and trust it too much.</p>
<p>In this second iteration, Antigravity added lefthook without any problem, but it didn’t remove all the <code>husky</code> references. In fact, if you check the <a target="_blank" href="https://github.com/Puppo/the-mood-mirror/commit/1ca9fed538fa1ee15f3e8dd07ac149e01ee68bf3">commit</a>, you can see the <code>_husky</code> folder with two files, with no sense script for this repo, and in the <code>package.json</code>, it forgot to remove the <code>prepare</code> script.</p>
<p>As you can see, our code review when using these tools is crucial to avoid trash or unnecessary code.</p>
<h2 id="heading-the-gemini-30-integration">The Gemini 3.0 integration</h2>
<p>The next test was the Gemini integration to build the Sentiment analysis service.<br />As I did in the previous tests, I started from a new chat.<br />The prompt in this case was a bit more articulated. I asked to generate a service that accepts a text and, through Gemini, returns a structured result with these fields:</p>
<ul>
<li><p><em>moodScore</em>: a value between 0 and 1 to determine the mood score</p>
</li>
<li><p><em>promptType</em>: This is the value that determines if the mirror will show an image or a video</p>
</li>
<li><p><em>promptText</em>: This is the text to pass later to generate the video or the image</p>
</li>
</ul>
<p>This result must later be used to generate an image or a video using NanoBanana Pro or Veo 3.</p>
<p>This iteration has been a bit convoluted. The first version used the old npm package <code>@google/generative-ai</code> and not the new one <code>@google/genai</code>. So I kept reiterating to get the code updated to the new version of the SDK. Another issue I had was that Antigravity created a single file to handle both images and videos. So, for that, I reiterated the need to split the logic for image and video generation into two separate files, and I also fixed the video generation to use the video model instead of the image model.</p>
<p>After that, I got a working application that met my first requirements, and you can see a demo in the video below. <em>[and</em> <a target="_blank" href="https://github.com/Puppo/the-mood-mirror/commit/9dc0d5f74ee505ecf3f04f7baa53248eeea0e331#diff-053150b640a7ce75eff69d1a22cae7f0f94ad64ce9a855db544dda0929316519"><em>here</em></a> <em>you can check the commit]</em></p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://www.youtube.com/watch?v=098qvXvpVZQ">https://www.youtube.com/watch?v=098qvXvpVZQ</a></div>
<p> </p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>It’s time to wrap up this first experience with Antigravity.</p>
<p>Overall, the experience with the tool was good. This is its first version, and only a few weeks after its release, Antigravity showed great DX and a good understanding of what I want to achieve.</p>
<p>Yes, it is not perfect, and in some cases, the plan described at the beginning hasn’t been satisfied. But this also happens with IDEs that have been in place for months.</p>
<p>As with the other Agentic IDEs, including Antigravity, developer checks are key to boosting implementation velocity while maintaining codebase quality.</p>
<p>The planning mode is fantastic in my opinion, because taking a look at the plan and reviewing or confirming it before starting the implementation can reduce the time wasted on reiterating the Agent result; as we saw, it’s still not perfect yet, but I’m pretty sure it will be tuned and improved in the future.</p>
<p>If I had to rate this first experience, I'd give it <strong>7/10</strong> because the flow was excellent, but I expected more precise results.</p>
<p>Okay, that’s all. I hope you enjoyed this article. Let me know in the comments your experience with Antigravity or other Agentic IDEs.</p>
<p>Bye Bye 👋</p>
]]></content:encoded></item><item><title><![CDATA[Improve Your Git Commit Messages with GitLens Tips]]></title><description><![CDATA[In the AI era, we can do many different things with LLM: generate code, images, videos or ask whatever we want and wait for an answer.The AI is here, and we cannot snub it. I love using it to simplify my day, help me find solutions, or learn new thin...]]></description><link>https://blog.delpuppo.net/improve-your-git-commit-messages-with-gitlens-tips</link><guid isPermaLink="true">https://blog.delpuppo.net/improve-your-git-commit-messages-with-gitlens-tips</guid><category><![CDATA[Git]]></category><category><![CDATA[gitlens]]></category><category><![CDATA[gitkraken]]></category><category><![CDATA[commit messages]]></category><category><![CDATA[commit]]></category><category><![CDATA[AI]]></category><category><![CDATA[#ai-tools]]></category><dc:creator><![CDATA[Luca Del Puppo]]></dc:creator><pubDate>Fri, 03 Oct 2025 06:06:40 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/VrWyKyITBQs/upload/075d83ce0b66b153f200f6b1b5b93ba3.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In the AI era, we can do many different things with LLM: generate code, images, videos or ask whatever we want and wait for an answer.<br />The AI is here, and we cannot snub it. I love using it to simplify my day, help me find solutions, or learn new things. For instance, one of the most challenging tasks I perform every day is crafting a commit message for my next commit. I love to commit often, and I avoid commit messages like “WIP”, “work in progress”, “first step”, “second step”, and so on.<br />In the past, I spent a considerable amount of time crafting the perfect commit message for the next commit. Currently, thanks to <a target="_blank" href="https://www.gitkraken.com/gitlens">GitLens</a> (by <a target="_blank" href="https://www.gitkraken.com/">GitKraken</a>), I can ask for help from the AI to generate a prefilled message based on my actions, and then review the generated message.</p>
<h2 id="heading-how-to-generate-messages">How to generate messages</h2>
<p>To generate the commit messages, first of all, you have to change your codebase 😎<br />After that, when you are ready to commit, it’s time to generate the message.<br />To do that, you need to go to the Source Control panel in <a target="_blank" href="https://code.visualstudio.com/">VSCode,</a> and if you have the <a target="_blank" href="https://www.gitkraken.com/gitlens">GitLens</a> extension installed, you can use the “Magic” icon to generate the message.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1757526339717/5be16f0c-c4a7-4c3c-b54a-69221c17f656.png" alt class="image--center mx-auto" /></p>
<p>If you click the button, you should have three options</p>
<ol>
<li><p>Generate Commit Message with GitLens</p>
</li>
<li><p>Compose Commit (Preview)</p>
</li>
<li><p>Switch GitLens AI Provider/Model</p>
</li>
</ol>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1757526614655/cb3b35b6-2be9-4734-afe2-d239ec2e48cb.png" alt class="image--center mx-auto" /></p>
<p>It goes without saying that the first option is the correct one to use when generating your commit message.</p>
<p>After clicking the button, you must wait for a couple of seconds, and the result will appear in the text box.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1757526749686/3de71875-6d01-406f-8214-fe8b92c0e9aa.png" alt class="image--center mx-auto" /></p>
<p>As you can see, the result is excellent. A commit message that follows the conventional commit rules and a small description of what happened in the code.</p>
<p>Now, you can decide whether the message is okay and commit without changing it, or review it and then commit with your edited message.</p>
<h2 id="heading-custom-instructions">Custom Instructions</h2>
<p>As with all AI features, instructions are crucial to achieving the best possible result.<br />Also, for this feature, we can set up instructions to guide the AI in creating the messages.<br />To do that, you have to go to Settings and search for “GitLens commit message AI custom instruction”.<br />You should find an option “<strong>Gitlens › Ai › Generate Commit Message: Custom Instructions (Preview)”</strong>, and this option has a text box that you can fill.<br />In my case, I inserted this instruction: “Please generate the commit message in the format of conventional commit,” but you can insert all the instructions that you want.<br />These instructions will help the AI generate the best messages based on your needs, and they will likely reduce the changes required to achieve the best message in the end.</p>
<h2 id="heading-conclusions">Conclusions</h2>
<p>As you can see, this feature is pretty simple but very helpful. It can reduce the time you spend generating commit messages and help you describe the intention of your commits in the best way.<br />I use it daily, and it helps me to be more precise in my commit messages, which in turn helps me summarise the commit in the best way.<br /><em>N.B. I’m not a native English speaker, and this feature helps me express myself in the best possible way in my commits.</em></p>
<p>Okay, that’s all, folks. I hope you’ve enjoyed the content and found it helpful.<br />See you soon</p>
<p>Bye Bye 👋</p>
]]></content:encoded></item><item><title><![CDATA[Do you really need the Cloud to work with AI?]]></title><description><![CDATA[We are in the AI era. New models emerge daily, and many applications have already integrated AI into their workflows.
Gemini, OpenAI, Copilot, Deepseek, Llama, and many others enable AI in your applications or help you write code, but they all need a...]]></description><link>https://blog.delpuppo.net/do-you-really-need-the-cloud-to-work-with-ai</link><guid isPermaLink="true">https://blog.delpuppo.net/do-you-really-need-the-cloud-to-work-with-ai</guid><category><![CDATA[gemini-nano]]></category><category><![CDATA[AISprint ]]></category><category><![CDATA[geminiAPI]]></category><category><![CDATA[Chrome]]></category><category><![CDATA[AI]]></category><category><![CDATA[browser]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[TypeScript]]></category><category><![CDATA[GitHub]]></category><dc:creator><![CDATA[Luca Del Puppo]]></dc:creator><pubDate>Wed, 25 Jun 2025 06:00:57 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/dUMEnARXgJU/upload/5d2d9468d872d56002ce279a15edd794.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>We are in the AI era. New models emerge daily, and many applications have already integrated AI into their workflows.</p>
<p><a target="_blank" href="https://gemini.google.com/">Gemini</a>, <a target="_blank" href="https://openai.com/">OpenAI</a>, <a target="_blank" href="https://copilot.microsoft.com/">Copilot</a>, <a target="_blank" href="https://www.deepseek.com/">Deepseek</a>, <a target="_blank" href="https://www.llama.com/">Llama</a>, and many others enable AI in your applications or help you write code, but they all need an internet connection to be accessible. You need the Cloud or to connect to a managed service to get an answer from the model. In some scenarios, this approach exposes you to security issues or the risk of sharing data with another service, and you may want to avoid it.</p>
<p>To help the team and companies benefit from AI and avoid these issues, the Chrome team is working to make Gemini (nano) part of the Chrome browser. The idea is to download the models in the browser when you have connectivity and use them directly from the browser, offline, if needed.</p>
<p>So let's see how it works 🚀</p>
<p><em>These features are on the building; most are available only under the Canary version and feature flag. If you are interested, you can find all the info at this</em> <a target="_blank" href="https://developer.chrome.com/docs/ai/built-in"><em>link</em></a><em>.</em></p>
<h2 id="heading-features-available">Features available</h2>
<p>As you've already understood, only limited features are available; some are stable, and some are not.</p>
<p>Let's start by listing the features, and later, we will look at some of them.</p>
<p>The available API are:</p>
<ul>
<li><p><a target="_blank" href="https://developer.chrome.com/docs/ai/translator-api">Translator API</a></p>
</li>
<li><p><a target="_blank" href="https://developer.chrome.com/docs/ai/language-detection">Language Detector</a></p>
</li>
<li><p><a target="_blank" href="https://developer.chrome.com/docs/ai/summarizer-api">Summarizer API</a></p>
</li>
<li><p><a target="_blank" href="https://developer.chrome.com/docs/ai/writer-api">Writer API</a></p>
</li>
<li><p><a target="_blank" href="https://developer.chrome.com/docs/ai/rewriter-api">Rewriter API</a></p>
</li>
<li><p><a target="_blank" href="https://developer.chrome.com/docs/ai/prompt-api">Prompt API</a></p>
</li>
<li><p><a target="_blank" href="https://developer.chrome.com/docs/ai/built-in-apis#proofreader_api">Proofreader API</a></p>
</li>
</ul>
<p>Some are stable from Chrome 138, and some are available for local experiments; you can check out the status of the APIs <a target="_blank" href="https://developer.chrome.com/docs/ai/built-in-apis#proofreader_api">here</a> so you can be sure about the current situation when you read this post.</p>
<p>As you can see, the APIs' names are fantastic, and they explain their behaviour.</p>
<p>If you want to try these features, start from <a target="_blank" href="https://developer.chrome.com/docs/ai/get-started">this documentation</a> section. Unfortunately, you must enable the features through the configurations, so follow these steps to get a Chrome instance ready to run AI models directly from your laptop.</p>
<p>Before closing this chapter, here is a quick reflection on these APIs. As you can notice, all of them work with text; some produce, some detect, some translate, and so on. So, for now, you can work with text and not produce images or videos from the browser, but it's a great starting point!</p>
<h2 id="heading-lets-talk-about-features">Let's talk about features</h2>
<h3 id="heading-language-detector">Language Detector</h3>
<p>The language detector API is one of the features available from Chrome 138. It allows you to detect the language of a specific word or phrase.</p>
<p>It returns a list of possible languages with the confidence score for that language. This means that we need to make a strategy to choose the best language for our application, but in most cases, the language with the best score is the best one for our application!</p>
<p><strong>How it works!</strong></p>
<p>One thing to do is check if the API is available or not to prevent errors.</p>
<p>To do that, you must check the <code>self</code> object.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">if</span> (<span class="hljs-string">'LanguageDetector'</span> <span class="hljs-keyword">in</span> self) {
  <span class="hljs-comment">// Language Detector Available</span>
}
</code></pre>
<p>Then, you must check if the model is already available in your browser or if you need to download it.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">const</span> availability = <span class="hljs-keyword">await</span> LanguageDetector.availability();
</code></pre>
<p>This result can have four possible values:</p>
<ul>
<li><p><code>"unavailable"</code>: The requested options are unsupported, or the model cannot be prompted.</p>
</li>
<li><p><code>"downloadable"</code>: The request is supported, but you need to download additional files before creating a session. These downloads may include the language model or fine-tuning.</p>
</li>
<li><p><code>"downloading"</code>: The request is supported and a download is ongoing, which must be completed before creating a session..</p>
</li>
<li><p><code>"available"</code>: The request is supported, and you can create a session.</p>
</li>
</ul>
<p><em>This method is pretty much the same for all APIs. Following this flow, you can check if a specific API is available.</em></p>
<p>When you reach the <code>available</code> status, you are finally ready to work with the <strong>LanguageDetector</strong> API, and you can create an instance of it by following the next code.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">const</span> instance = <span class="hljs-keyword">await</span> LanguageDetector.create();
<span class="hljs-keyword">const</span> result = <span class="hljs-keyword">await</span> instance.detect(<span class="hljs-string">'Hello world!'</span>);

<span class="hljs-comment">// result = [{</span>
<span class="hljs-comment">//   detectedLanguage: 'en',</span>
<span class="hljs-comment">//   confidence: 0.9973934888839722</span>
<span class="hljs-comment">// }];</span>
</code></pre>
<p>As you can see, this API is straightforward and pretty easy to learn.<br />With that, you have completed your first learning about AI in Chrome with Gemini Nano, and it’s time to move on to another fantastic API!</p>
<p><em>N.B. If you are working with</em> <a target="_blank" href="https://www.typescriptlang.org/"><em>TypeScript</em></a> <em>and want to get the best DX possible, a types package that simplifies your work and enables IntelliSense for these APIs exists.</em> <code>@types/dom-chromium-ai</code> <em>This is the name of the package, and we have to thank you,</em> <a target="_blank" href="https://github.com/christianliebel"><em>Christian Liebel</em></a> <em>and</em> <a target="_blank" href="https://github.com/tomayac"><em>Thomas Steiner</em></a><em>, for it.</em></p>
<h3 id="heading-translator-api">Translator API</h3>
<p>Translator API is one of the most common features for an AI. It's pretty simple: you send a text, and you will receive the text translated. This API is available from Chrome 138.<br />But let’s see how it works.</p>
<p><strong>How it works!</strong></p>
<p>First, you must check if the API is available in the browser.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">if</span> (<span class="hljs-string">'Translator'</span> <span class="hljs-keyword">in</span> self) {
  <span class="hljs-comment">// Translator API available</span>
}
</code></pre>
<p>If the API is enabled, you must check if the languages you need for source and target are available.<br />To do that, you must use the <code>availability</code> method exposed by the <code>Translator</code> object.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">const</span> translatorCapabilities = <span class="hljs-keyword">await</span> Translator.availability({
  sourceLanguage: <span class="hljs-string">'en'</span>,
  targetLanguage: <span class="hljs-string">'it'</span>,
});
</code></pre>
<p>The result of this method can have four different values:</p>
<ul>
<li><p><code>"unavailable"</code>: The implementation does not support translation of the given languages.</p>
</li>
<li><p><code>"downloadable"</code>: The implementation supports translation of the given languages, but a download is required to proceed. The download may be the browser model.</p>
</li>
<li><p><code>"downloading"</code>: The implementation supports translation of the given languages. The browser is finishing an ongoing download, as part of creating the associated object.</p>
</li>
<li><p><code>"available"</code>: The implementation supports translation of the given languages, and any required downloads are already complete.</p>
</li>
</ul>
<p>Now, if you don’t receive <code>"unavailable"</code>, you can create the translator instance. This method will download the model for you if it hasn’t already been downloaded.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">const</span> translator = <span class="hljs-keyword">await</span> Translator.create({
  sourceLanguage: <span class="hljs-string">'en'</span>,
  targetLanguage: <span class="hljs-string">'it'</span>,
  monitor(m) {
    m.addEventListener(<span class="hljs-string">'downloadprogress'</span>, <span class="hljs-function">(<span class="hljs-params">e</span>) =&gt;</span> {
      <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Downloaded <span class="hljs-subst">${e.loaded * <span class="hljs-number">100</span>}</span>%`</span>);
    });
  },
});
</code></pre>
<p>As you can see, using the <code>create</code> method, you can create your instance and pass your source and target languages. Then, using the <code>monitor</code> method, you can listen to the download progress and maybe create a loader for the user to provide feedback and create a better UX experience. Obviously, the promise will fail if something goes wrong during the download, and you must handle it.<br />But if everything is okay, you can use the new <code>translator</code> instance to translate the text by using the <code>translate</code> method.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">await</span> translator.translate(<span class="hljs-string">'Where is the next bus stop, please?'</span>);
<span class="hljs-comment">// Dov'è la prossima fermata dell'autobus, per favore?</span>
</code></pre>
<p>One important thing to know about this API is that it processes messages sequentially. So, if you have many messages, you must keep this limitation in mind. Then, if you need to translate large amounts of text, it’s better to chunk it and create a <a target="_blank" href="https://web.dev/articles/building/a-loading-bar-component">loading interface</a> as feedback for the user.</p>
<p>As is evident, this API is also straightforward. There are some methods to learn, and you can integrate this API into your applications by using them.</p>
<p><em>Also, for this API, you can use the</em> <code>@types/dom-chromium-ai</code> <em>package to get a better experience with</em> <a target="_blank" href="https://www.typescriptlang.org/"><em>TypeScript</em></a><em>.</em></p>
<h3 id="heading-summarizer-api">Summarizer API</h3>
<p>The last API you will meet in this article is the Summarizer API.<br />This API enable you to summarise small or large text. Also, this API is available from Chrome 138 stable.</p>
<p><strong>How it works!</strong></p>
<p>First, you must check if the API is available in the browser.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">if</span> (<span class="hljs-string">'Summarizer'</span> <span class="hljs-keyword">in</span> self) {
  <span class="hljs-comment">// Summarizer API available</span>
}
</code></pre>
<p>If the API is enabled, then you must check if the model is available.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">const</span> summarizerCapabilities = <span class="hljs-keyword">await</span> Summarizer.availability();
</code></pre>
<p>Also, for this method, the possible results can be:</p>
<ul>
<li><p><code>"unavailable"</code> means that the implementation does not support the requested options.</p>
</li>
<li><p><code>"downloadable"</code> means that the implementation supports the requested options, but first, the browser has to download something, such as a model (in Chrome's case, Gemini Nano) or fine-tuning for the model.</p>
</li>
<li><p><code>"downloading"</code> means that the implementation supports the requested options, but it has to finish an ongoing download before it can proceed.</p>
</li>
<li><p><code>"available"</code> means that the implementation supports the requested options and the summarizer can proceed.</p>
</li>
</ul>
<p>Now, if everything is okay, it’s time to create an instance of the Summarizer API.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">const</span> summarizer = <span class="hljs-keyword">await</span> Summarizer.create({
  monitor(m) {
    m.addEventListener(<span class="hljs-string">'downloadprogress'</span>, <span class="hljs-function">(<span class="hljs-params">e</span>) =&gt;</span> {
      <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Downloaded <span class="hljs-subst">${e.loaded * <span class="hljs-number">100</span>}</span>%`</span>);
    });
  }
});
</code></pre>
<p>This <code>create</code> method exposes the <code>monitor</code> function to listen to the download progress and create a better experience for the user as well.<br />This <code>create</code> method has different parameters you can pass to get different types of summaries or drive the summary's length.</p>
<p>These parameters are:</p>
<ul>
<li><p><code>sharedContext</code>: Additional shared context that can help the summarizer.</p>
</li>
<li><p><code>type</code>: The type of summarisation, with the allowed values <code>key-points</code> (<strong><em>default</em></strong>), <code>tldr</code>, <code>teaser</code>, and <code>headline</code>. To learn more about them, follow this <a target="_blank" href="https://developer.chrome.com/docs/ai/summarizer-api">link</a>.</p>
</li>
<li><p><code>format</code>: The format of the summarisation, with the allowed values <code>markdown</code> (default) and <code>plain-text</code>.</p>
</li>
<li><p><code>length</code>: The length of the summarisation, with the allowed values <code>short</code>, <code>medium</code> (default), and <code>long</code>. The meanings of these lengths vary depending on the requested <code>type</code>.</p>
</li>
</ul>
<p>It's important to know that parameters can’t be changed. So, once you create a new instance, if you need to modify the parameters, you must create a new instance.</p>
<p>Now that you have the summarizer instance, you can use it to summarise the text.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">const</span> longText = <span class="hljs-string">'Blah blah blah......'</span>;
<span class="hljs-keyword">const</span> summary = <span class="hljs-keyword">await</span> summarizer.summarize(longText, {
  context: <span class="hljs-string">'This is a recipe.'</span>,
});
</code></pre>
<p>This API also exposes another method, just in case you want to stream the summary result and make it available “faster.”<br />To do that, you need to use the <code>summarizeStreaming</code> method instead of the <code>summarize</code> one.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">const</span> longText = <span class="hljs-string">'Blah blah blah......'</span>;
<span class="hljs-keyword">const</span> summary = <span class="hljs-keyword">await</span> summarizer.summarizeStreaming(longText, {
  context: <span class="hljs-string">'This is a recipe.'</span>,
});
</code></pre>
<p>And with that, you learnt the last AI API for Browsers available in this article 😃</p>
<p>Like the others, this API is straightforward too. There are just some methods to know, and you can integrate this API into your applications.</p>
<h2 id="heading-recipe-radar-with-ai-app">Recipe Radar with AI App</h2>
<p>I wrote a lot in this article, I know, but to let you know how these APIs work. I created a sample app with some recipes. On the detail page, you can see the Language Detector and Translator API in action. Therefore, on the search page, you can see the Summarizer API in action to summarise the recipe and return a summary of the recipe to the user.<br />If you are interested in it, here is the link to the repo and to the website:</p>
<ul>
<li><p><em>Github Repo</em>: <a target="_blank" href="https://github.com/Puppo/recipe-radar-with-ai">https://github.com/Puppo/recipe-radar-with-ai</a></p>
</li>
<li><p><em>GitHub Page Website:</em> <a target="_blank" href="https://puppo.github.io/recipe-radar-with-ai/">https://puppo.github.io/recipe-radar-with-ai/</a></p>
</li>
</ul>
<p>Please don’t take too much care of the code structure. I vibe-coded the application's structure to reduce the time it took to create, and I spent more time on the AI feature and its integration.</p>
<p>By the way, this application example implements and runs all these APIS on a website. It’s important to test in a Chrome version with these APIs available.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Okay, it’s time to wrap up!<br />In this article, you learn how to integrate AI inside the Browser without relying on any services or cloud providers.<br />You learnt how to use Language Detector, Translator, and Summarizer API on the Web and what they look like.<br />Remember that these new features are not available in all browsers, so please be careful when using them in production.</p>
<p>That’s it, folks. I hope you enjoyed the content. If so, please leave a comment or a reaction!</p>
<p>See you soon with other awesome content 🚀</p>
<p>Bye Bye 👋</p>
<p><em>Google Cloud credits are provided for this project.</em> #AISprint</p>
]]></content:encoded></item><item><title><![CDATA[A Promise is forever]]></title><description><![CDATA[In the ever-evolving world of web development, mastering asynchronous operations is a crucial skill for any JavaScript developer. Asynchronous programming allows web applications to handle tasks like API requests, file operations, or any activities t...]]></description><link>https://blog.delpuppo.net/a-promise-is-forever</link><guid isPermaLink="true">https://blog.delpuppo.net/a-promise-is-forever</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[promises]]></category><category><![CDATA[async]]></category><category><![CDATA[async/await]]></category><category><![CDATA[await]]></category><category><![CDATA[promise]]></category><category><![CDATA[ES6]]></category><dc:creator><![CDATA[Luca Del Puppo]]></dc:creator><pubDate>Tue, 06 Feb 2024 06:13:01 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1706992845942/e157d0d3-0063-43b4-b1bb-ae66229aa5cf.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In the ever-evolving world of web development, mastering asynchronous operations is a crucial skill for any JavaScript developer. Asynchronous programming allows web applications to handle tasks like API requests, file operations, or any activities that require waiting for results without blocking the main thread. Traditionally, this was managed through callback functions, leading to the infamous "callback hell," where code becomes tangled and difficult to maintain. Enter JavaScript Promises - a powerful and elegant solution to simplify asynchronous code management.</p>
<p>Promises in JavaScript represent the eventual completion or failure of an asynchronous operation and its resulting value. They not only provide a cleaner and more manageable way to handle asynchronous tasks but also offer improved error handling and readability. This makes them an indispensable tool in the modern JavaScript developer's toolkit.</p>
<p>In this comprehensive guide, we'll embark on a journey to unravel the mysteries of JavaScript Promises. From their fundamental concepts to advanced techniques, we will explore how Promises can streamline your code and make handling asynchronous operations a breeze. Whether you're just starting your journey with JavaScript or are a seasoned developer, this post aims to enhance your understanding and skills in working with Promises.</p>
<p>So, let's dive in and unlock the full potential of JavaScript Promises, transforming the way you write and manage asynchronous code!</p>
<h2 id="heading-section-1-understanding-promises"><strong>Section 1: Understanding Promises</strong></h2>
<h3 id="heading-what-is-a-promise"><strong>What is a Promise?</strong></h3>
<p>At its core, a JavaScript Promise is an object that represents the eventual completion or failure of an asynchronous operation and its resulting value. Unlike the immediate return of values in synchronous code, a Promise gives us a placeholder for a future value, which we can work with in a more structured and predictable manner.</p>
<p>This approach solves many issues associated with older, callback-based patterns, commonly known as "callback hell." Promises allow for more readable and maintainable code, especially when dealing with complex sequences of asynchronous operations.</p>
<h3 id="heading-creating-a-promise"><strong>Creating a Promise</strong></h3>
<p>A Promise in JavaScript is created using the <code>Promise</code> constructor. It takes a function as its argument, known as the executor function. This executor function is called immediately by the Promise implementation and it receives two functions as parameters: <code>resolve</code> and <code>reject</code>.</p>
<ul>
<li><p><code>resolve</code> is called when the asynchronous task completes successfully, passing the result.</p>
</li>
<li><p><code>reject</code> is used when the task fails, passing the error or reason for failure.</p>
</li>
</ul>
<p>Here's a basic example of creating a Promise:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">let</span> myPromise = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve, reject</span>) =&gt;</span> {
    <span class="hljs-comment">// Asynchronous operation code here</span>
    <span class="hljs-keyword">if</span>(<span class="hljs-comment">/* operation successful */</span>) {
        resolve(<span class="hljs-string">'Success'</span>);
    } <span class="hljs-keyword">else</span> {
        reject(<span class="hljs-string">'Error'</span>);
    }
});
</code></pre>
<p>In this example, the Promise will either resolve with <code>Success</code> or reject with <code>Error</code>, depending on the outcome of the asynchronous operation encapsulated within it.</p>
<h3 id="heading-promise-states"><strong>Promise States</strong></h3>
<p>A Promise can be in one of three states:</p>
<ol>
<li><p><strong>Pending</strong>: The initial state of a Promise. The operation has not been completed yet.</p>
</li>
<li><p><strong>Fulfilled</strong>: The operation was completed successfully, and the Promise now holds the resulting value.</p>
</li>
<li><p><strong>Rejected</strong>: The operation failed, and the Promise holds the reason for the failure.</p>
</li>
</ol>
<p>This state model ensures that a Promise can only be resolved or rejected once and its state and value become immutable after that change.</p>
<p>Understanding these foundational concepts is crucial for working effectively with Promises in JavaScript. They form the building blocks upon which more complex asynchronous operations can be built, allowing for more readable and maintainable code.</p>
<h2 id="heading-section-2-working-with-promises"><strong>Section 2: Working with Promises</strong></h2>
<h3 id="heading-then-catch-and-finally"><strong>then, catch, and finally</strong></h3>
<p>After creating a Promise, the next step is handling its resolution or rejection. This is where the methods <code>then</code>, <code>catch</code>, and <code>finally</code> come into play.</p>
<ul>
<li><p><strong>then</strong>: This method is used to access the result of a Promise if it is successfully resolved. It takes up to two functions as arguments: the first for the resolved case and the second for the rejected case.</p>
<pre><code class="lang-javascript">  myPromise
  .then(
      <span class="hljs-function"><span class="hljs-params">result</span> =&gt;</span> { <span class="hljs-built_in">console</span>.log(result); },  <span class="hljs-comment">// Success handler</span>
      <span class="hljs-function"><span class="hljs-params">error</span> =&gt;</span> { <span class="hljs-built_in">console</span>.error(error); }  <span class="hljs-comment">// Error handler</span>
  );
</code></pre>
</li>
<li><p><strong>catch</strong>: This method is used for error handling in Promises. It is essentially a shorthand for <code>then(null, rejection)</code>.</p>
<pre><code class="lang-javascript">  <span class="hljs-built_in">Promise</span>.catch(<span class="hljs-function"><span class="hljs-params">error</span> =&gt;</span> { <span class="hljs-built_in">console</span>.error(error); });
</code></pre>
</li>
<li><p><strong>finally</strong>: Introduced in ES2018, <code>finally</code> is a method that executes a specified piece of code when the Promise is settled, regardless of its outcome (resolved or rejected). It's useful for cleanup actions.</p>
<pre><code class="lang-javascript">  <span class="hljs-built_in">Promise</span>.finally(<span class="hljs-function">() =&gt;</span> {
      <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Operation completed.'</span>);
  });
</code></pre>
</li>
</ul>
<h3 id="heading-chaining-promises"><strong>Chaining Promises</strong></h3>
<p>One of the key strengths of Promises is their ability to be chained. This is done by returning another Promise in the <code>then</code> method, which allows for sequential asynchronous operations.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve, reject</span>) =&gt;</span> {
    <span class="hljs-built_in">setTimeout</span>(<span class="hljs-function">() =&gt;</span> resolve(<span class="hljs-number">1</span>), <span class="hljs-number">1000</span>);
})
.then(<span class="hljs-function"><span class="hljs-params">result</span> =&gt;</span> {
    <span class="hljs-built_in">console</span>.log(result); <span class="hljs-comment">// 1</span>
    <span class="hljs-keyword">return</span> result * <span class="hljs-number">2</span>; 
})
.then(<span class="hljs-function"><span class="hljs-params">result</span> =&gt;</span> {
    <span class="hljs-built_in">console</span>.log(result); <span class="hljs-comment">// 2</span>
    <span class="hljs-keyword">return</span> result * <span class="hljs-number">3</span>;
})
.then(<span class="hljs-function"><span class="hljs-params">result</span> =&gt;</span> {
    <span class="hljs-built_in">console</span>.log(result); <span class="hljs-comment">// 6</span>
    <span class="hljs-keyword">return</span> result * <span class="hljs-number">4</span>;
});
</code></pre>
<p>In this chain, each <code>then</code> receives the result of the previous operation, allowing for a sequence of asynchronous tasks to be handled in a clean and readable manner.</p>
<h3 id="heading-error-handling-in-promises"><strong>Error Handling in Promises</strong></h3>
<p>Error handling is crucial in asynchronous code. In a Promise chain, if an error is thrown in any of the <code>then</code> methods, it propagates down the chain until it is caught by a <code>catch</code> method. This makes it easier to manage errors in complex asynchronous code.</p>
<pre><code class="lang-javascript">doSomething()
.then(<span class="hljs-function"><span class="hljs-params">result</span> =&gt;</span> doSomethingElse(result))
.then(<span class="hljs-function"><span class="hljs-params">newResult</span> =&gt;</span>doThirdThing(newResult))
.catch(<span class="hljs-function"><span class="hljs-params">error</span> =&gt;</span> <span class="hljs-built_in">console</span>.error(error))
.finally(<span class="hljs-function">() =&gt;</span><span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Operation done'</span>));
</code></pre>
<h3 id="heading-real-world-examples"><strong>Real-world Examples</strong></h3>
<p>Promises are particularly useful when dealing with API requests. For example, fetching data from a remote server:</p>
<pre><code class="lang-javascript">fetch(<span class="hljs-string">'https://api.example.com/data'</span>)
    .then(<span class="hljs-function"><span class="hljs-params">response</span> =&gt;</span> response.json())
    .then(<span class="hljs-function"><span class="hljs-params">data</span> =&gt;</span> <span class="hljs-built_in">console</span>.log(data))
    .catch(<span class="hljs-function"><span class="hljs-params">error</span> =&gt;</span> <span class="hljs-built_in">console</span>.error(<span class="hljs-string">'Error:'</span>, error));
</code></pre>
<p>This section on working with Promises is critical for understanding how to effectively implement and manage asynchronous operations in JavaScript. It covers the fundamental methods for handling Promises and demonstrates the power of chaining for complex tasks, along with practical examples that the readers can relate to and implement in their own projects.</p>
<h2 id="heading-section-3-advanced-promise-concepts"><strong>Section 3: Advanced Promise Concepts</strong></h2>
<h3 id="heading-asyncawait-syntax"><strong>Async/Await Syntax</strong></h3>
<p>Introduced in ES2017, async/await is a syntactic feature in JavaScript that allows you to work with Promises in a more synchronous-like manner, making your asynchronous code look and behave a bit more like synchronous code.</p>
<ul>
<li><p><strong>Async Functions</strong>: Declaring a function as <code>async</code> automatically wraps its return value in a Promise. This means you can use <code>await</code> within these functions to pause the execution until the awaited Promise is resolved.</p>
<pre><code class="lang-javascript">  <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">asyncFunction</span>(<span class="hljs-params"></span>) </span>{
      <span class="hljs-keyword">const</span> result = <span class="hljs-keyword">await</span> someAsyncOperation();
      <span class="hljs-built_in">console</span>.log(result); <span class="hljs-keyword">return</span> <span class="hljs-string">'Completed'</span>;
  }
</code></pre>
</li>
<li><p><strong>Await</strong>: The <code>await</code> keyword is used to pause the execution of an async function until a Promise is resolved, allowing you to write cleaner and more readable asynchronous code.</p>
<pre><code class="lang-javascript">  <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">fetchData</span>(<span class="hljs-params"></span>) </span>{ 
      <span class="hljs-keyword">try</span> {
          <span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> fetch(<span class="hljs-string">'https://api.example.com/data'</span>);
          <span class="hljs-keyword">const</span> data = <span class="hljs-keyword">await</span> response.json();<span class="hljs-built_in">console</span>.log(data);
      } <span class="hljs-keyword">catch</span> (error) {
          <span class="hljs-built_in">console</span>.error(<span class="hljs-string">'Fetch error:'</span>, error);
      }
  }
</code></pre>
</li>
</ul>
<h3 id="heading-error-handling-in-asyncawait"><strong>Error Handling in Async/Await</strong></h3>
<p>Error handling in async/await is achieved using try/catch blocks, making it syntactically similar to synchronous error handling.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">safeFetch</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">try</span> {
        <span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> fetch(<span class="hljs-string">'https://api.example.com/data'</span>);
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">await</span> response.json();
    } <span class="hljs-keyword">catch</span> (error) {
        <span class="hljs-built_in">console</span>.error(<span class="hljs-string">'Fetch failed:'</span>, error);
        <span class="hljs-keyword">throw</span> error; <span class="hljs-comment">// Re-throwing the error is important for caller awareness</span>
    }
}
</code></pre>
<h3 id="heading-handling-multiple-promises"><strong>Handling Multiple Promises</strong></h3>
<h4 id="heading-promiseall">Promise.all</h4>
<p><code>Promise.all</code> is used when you need to wait for multiple Promises to complete. It takes an array of Promises and returns a new Promise that resolves when all of the input Promises resolve or rejects as soon as one of them rejects.</p>
<pre><code class="lang-javascript"><span class="hljs-built_in">Promise</span>.all([asyncTask1(), asyncTask2(), asyncTask3()])
.then(<span class="hljs-function"><span class="hljs-params">results</span> =&gt;</span> {<span class="hljs-built_in">console</span>.log(<span class="hljs-string">'All tasks completed:'</span>, results); })
.catch(<span class="hljs-function"><span class="hljs-params">error</span> =&gt;</span> { <span class="hljs-built_in">console</span>.error(<span class="hljs-string">'One of the tasks failed:'</span>, error); });
</code></pre>
<h4 id="heading-promiserace">Promise.race</h4>
<p><code>Promise.race</code> resolves or rejects as soon as one of the Promises in an iterable resolves or rejects, with the value or reason from that Promise.</p>
<pre><code class="lang-javascript"><span class="hljs-built_in">Promise</span>.race([asyncTask1(), asyncTask2(), asyncTask3()])
.then(<span class="hljs-function"><span class="hljs-params">result</span> =&gt;</span> {<span class="hljs-built_in">console</span>.log(<span class="hljs-string">'First task completed:'</span>, result); })
.catch(<span class="hljs-function"><span class="hljs-params">error</span> =&gt;</span> { <span class="hljs-built_in">console</span>.error(<span class="hljs-string">'One of the tasks failed:'</span>, error); });
</code></pre>
<h4 id="heading-promiseallsettled">Promise.allSettled</h4>
<p><code>Promise.allSettled</code> is a method that returns a Promise that resolves after all of the given Promises have either been resolved or rejected, with an array of objects describing the outcome of each Promise.</p>
<pre><code class="lang-javascript"><span class="hljs-built_in">Promise</span>.allSettled([asyncTask1(), asyncTask2(), asyncTask3()])
.then(<span class="hljs-function"><span class="hljs-params">results</span> =&gt;</span> { 
    results.forEach(<span class="hljs-function">(<span class="hljs-params">result</span>) =&gt;</span> {
        <span class="hljs-keyword">if</span> (result.status === <span class="hljs-string">'fulfilled'</span>) {
            <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Success:'</span>, result.value);
        } <span class="hljs-keyword">else</span> {
            <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Failure:'</span>, result.reason);
        }
    });
});
</code></pre>
<h4 id="heading-promiseany">Promise.any</h4>
<p><code>Promise.any</code> takes multiple Promises and as soon as one of the Promises resolves, it returns a single Promise that resolves with the value from that Promise. If all of the passed-in Promises reject, then the returned Promise is rejected with an <code>AggregateError</code>.</p>
<pre><code class="lang-javascript"><span class="hljs-built_in">Promise</span>.any([asyncTask1(), asyncTask2(), asyncTask3()])
.then(<span class="hljs-function"><span class="hljs-params">result</span> =&gt;</span> {<span class="hljs-built_in">console</span>.log(<span class="hljs-string">'First successful task:'</span>, result); })
.catch(<span class="hljs-function"><span class="hljs-params">error</span> =&gt;</span> { <span class="hljs-built_in">console</span>.error(<span class="hljs-string">'All promises failed:'</span>, error); });
</code></pre>
<p>These methods for handling multiple Promises are powerful tools in a JavaScript developer's arsenal. They offer different ways to manage multiple asynchronous operations, making it easier to write clean and efficient code. Understanding when and how to use each of these methods can significantly improve the way you handle concurrency in JavaScript.</p>
<h3 id="heading-understanding-promisewithresolvers"><strong>Understanding Promise.withResolvers</strong></h3>
<p>In the realm of JavaScript Promises, <code>Promise.withResolvers</code> could be conceptualized as a utility function designed to enhance the flexibility and control over Promise resolution and rejection. Unlike the standard Promise constructor, which encapsulates the executor function, <code>Promise.withResolvers</code> could provide direct access to the <code>resolve</code> and <code>reject</code> functions outside the Promise context. This feature would be particularly useful in scenarios where the resolution or rejection of a Promise needs to be triggered externally or in more complex control flows.</p>
<p>Imagine <code>Promise.withResolvers</code> functioning as follows:</p>
<pre><code class="lang-javascript"><span class="hljs-built_in">Promise</span>.withResolvers = <span class="hljs-built_in">Promise</span>.withResolvers ?? <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">let</span> resolve, reject;
  <span class="hljs-keyword">const</span> promise = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function">(<span class="hljs-params">res, rej</span>) =&gt;</span> {
    resolve = res;
    reject = rej;
  });
  <span class="hljs-keyword">return</span> { promise, resolve, reject };
}

<span class="hljs-keyword">const</span> { promise, resolve, reject } = <span class="hljs-built_in">Promise</span>.withResolvers();

promise.then(<span class="hljs-function"><span class="hljs-params">value</span> =&gt;</span> <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Resolved with: <span class="hljs-subst">${value}</span>`</span>))
       .catch(<span class="hljs-function"><span class="hljs-params">error</span> =&gt;</span> <span class="hljs-built_in">console</span>.error(<span class="hljs-string">`Rejected with: <span class="hljs-subst">${error}</span>`</span>));

<span class="hljs-comment">// The Promise can be resolved or rejected externally</span>
resolve(<span class="hljs-string">"Success!"</span>);
<span class="hljs-comment">// or reject("Failure");</span>
</code></pre>
<p>In this hypothetical implementation, <code>Promise.withResolvers</code> returns an object containing the Promise itself and its respective <code>resolve</code> and <code>reject</code> functions. This setup offers a more declarative way of handling Promises, especially in cases where the resolution condition is not immediately known or is dependent on external factors.</p>
<p>This approach, while offering more control, also requires careful management to avoid issues like unresolved Promises or memory leaks. It exemplifies the flexibility of Promises in JavaScript and how they can be tailored to fit specific programming paradigms or application needs. This method has been implemented in ES2023 but creates a polyfill for it; it is really a piece of cake as you can see.</p>
<h2 id="heading-section-4-under-the-hood"><strong>Section 4: Under the Hood</strong></h2>
<h3 id="heading-event-loop-and-promises"><strong>Event Loop and Promises</strong></h3>
<p>JavaScript's concurrency model revolves around the Event Loop, which plays a critical role in executing asynchronous code like Promises. Understanding this mechanism is key to mastering JavaScript's asynchronous behavior.</p>
<ul>
<li><p><strong>Event Loop</strong>: JavaScript has a single-threaded runtime, meaning it can only execute one command at a time. The event loop enables non-blocking operations by offloading tasks like I/O, timers, and HTTP requests, which are handled outside the JavaScript engine.</p>
</li>
<li><p><strong>Role of Promises</strong>: When a Promise is resolved or rejected, its callback is moved to the Microtask Queue, which is processed after the current execution stack is complete but before the event loop continues to the next iteration. This ensures that Promise callbacks are executed as soon as the JavaScript engine has the opportunity to do so, maintaining the non-blocking nature of asynchronous operations.</p>
</li>
</ul>
<h3 id="heading-creating-custom-promises"><strong>Creating Custom Promises</strong></h3>
<p>While many asynchronous operations are handled by built-in functions returning Promises, there are scenarios where you might need to create your own Promises.</p>
<ul>
<li><p><strong>Custom Promise Example</strong>: Let's say you're interfacing with a legacy API that uses callbacks, and you want to adapt it to use Promises for better code consistency and readability.</p>
<pre><code class="lang-javascript">  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">legacyApiFunction</span>(<span class="hljs-params">callback</span>) </span>{
    <span class="hljs-comment">// Simulating a callback-based API</span>
    <span class="hljs-built_in">setTimeout</span>(<span class="hljs-function">() =&gt;</span> {
      <span class="hljs-keyword">const</span> data = <span class="hljs-string">'some data'</span>;
      callback(<span class="hljs-literal">null</span>, data);
    }, <span class="hljs-number">1000</span>);
  }

  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">promisifyLegacyApi</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve, reject</span>) =&gt;</span> {
      legacyApiFunction(<span class="hljs-function">(<span class="hljs-params">err, data</span>) =&gt;</span> {
        <span class="hljs-keyword">if</span> (err) {
          reject(err);
        } <span class="hljs-keyword">else</span> {
          resolve(data);
        }
      });
    });
  }

  promisifyLegacyApi()
    .then(<span class="hljs-function"><span class="hljs-params">data</span> =&gt;</span> <span class="hljs-built_in">console</span>.log(data))
    .catch(<span class="hljs-function"><span class="hljs-params">error</span> =&gt;</span> <span class="hljs-built_in">console</span>.error(error));
</code></pre>
</li>
</ul>
<p>In this example, <code>promisifyLegacyApi</code> wraps the old callback-style function in a new Promise, providing a more modern, Promise-based interface for the same functionality.</p>
<h3 id="heading-best-practices-and-pitfalls"><strong>Best Practices and Pitfalls</strong></h3>
<ul>
<li><p><strong>Avoiding the "Promise Hell"</strong>: Similar to "callback hell," it's possible to end up in a situation with deeply nested Promises. To avoid this, leverage chaining and return Promises from within <code>then</code> callbacks, keeping the code flat.</p>
</li>
<li><p><strong>Error Handling</strong>: Always handle errors in Promises, either using <code>catch</code> for individual Promises or global error handlers for unhandled Promise rejections.</p>
</li>
<li><p><strong>Debugging</strong>: Debugging asynchronous code can be tricky. Utilize modern tools and techniques such as browser developer tools, which provide features to track and inspect Promises.</p>
</li>
</ul>
<p>If you want to dive deep into Promise, don't leave my YouTube video about it.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://youtu.be/ROwJX3i_m2Q?si=Fa9nC4H8C6grNiZF">https://youtu.be/ROwJX3i_m2Q?si=Fa9nC4H8C6grNiZF</a></div>
<p> </p>
<h2 id="heading-conclusion"><strong>Conclusion</strong></h2>
<p>As we conclude our journey through the world of JavaScript Promises, it's clear that they are much more than just a tool for handling asynchronous operations. They represent a fundamental shift in how we write and think about asynchronous code in JavaScript, offering a robust and elegant way to manage complex operations.</p>
<p>From understanding the basics of what a Promise is and how to create one, to exploring advanced concepts like <code>Promise.all</code>, <code>Promise.race</code>, <code>Promise.allSettled</code>, and <code>Promise.any</code>, we've covered a broad spectrum of functionalities that Promises provide. The async/await syntax further simplifies working with Promises, allowing for code that is not only more readable but also easier to maintain.</p>
<p>The real power of Promises lies in their ability to streamline complex asynchronous tasks, making our code cleaner, more efficient, and more reliable. By understanding the event loop and how Promises fit into JavaScript's concurrency model, developers can write more performant and bug-free code.</p>
<p>As you incorporate these concepts into your daily coding practices, remember that mastering Promises is a journey. There's always more to learn and new patterns to explore. Keep experimenting, keep learning, and most importantly, keep coding. The world of JavaScript is constantly evolving, and with tools like Promises at your disposal, you're well-equipped to tackle the challenges of modern web development.</p>
<p>Happy coding!</p>
<p><em>You can find the code of this article</em> <a target="_blank" href="https://github.com/Puppo/JavaScript-Examples/tree/01-promises"><em>here</em></a><em>.</em></p>
]]></content:encoded></item><item><title><![CDATA[The Reflect API: The Swiss Army Knife Every JavaScript Developer Needs]]></title><description><![CDATA[Ever wished for a magical toolkit that gives you superhero-like control over JavaScript objects? Say hello to the Reflect API, the Swiss Army knife every modern JavaScript developer needs! From peeping into objects to conjuring custom behaviors—Refle...]]></description><link>https://blog.delpuppo.net/the-reflect-api-the-swiss-army-knife-every-javascript-developer-needs</link><guid isPermaLink="true">https://blog.delpuppo.net/the-reflect-api-the-swiss-army-knife-every-javascript-developer-needs</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[js]]></category><category><![CDATA[reflect]]></category><dc:creator><![CDATA[Luca Del Puppo]]></dc:creator><pubDate>Thu, 09 Nov 2023 07:18:26 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1698179171407/ceb22e4b-92be-4c06-9bd2-9a44d35aef56.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Ever wished for a magical toolkit that gives you superhero-like control over JavaScript objects? Say hello to the <code>Reflect</code> API, the Swiss Army knife every modern JavaScript developer needs! From peeping into objects to conjuring custom behaviors—<code>Reflect</code> is your one-stop spellbook! 📜✨</p>
<p>Strap in as we teleport through this arcane realm of JavaScript, where we’ll not only decode <code>Reflect</code>, but also empower you with hands-on examples and practical tips! 🚀</p>
<h3 id="heading-core-objectives-of-reflect"><strong>🎯 Core Objectives of Reflect</strong></h3>
<ol>
<li><p><strong>Introspection</strong>: Much like looking into a magic mirror, <code>Reflect</code> allows you to delve into an object's properties and characteristics, enabling you to perform introspective tasks like checking property existence or retrieving property descriptors.</p>
</li>
<li><p><strong>Manipulation</strong>: Think of <code>Reflect</code> as your Swiss Army knife for object operations. You can easily add, delete, or modify object properties and even trap or monitor these operations.</p>
</li>
<li><p><strong>Extensibility</strong>: The <code>Reflect</code> API can be seen as a foundational layer that sets the stage for creating Proxy objects, empowering you to build custom behaviors for basic operations (like property lookup, assignment, enumeration, and more).</p>
</li>
</ol>
<h3 id="heading-reflect-methods">🛠️ <strong>Reflect Methods</strong></h3>
<h4 id="heading-1-reflectapply">1️⃣. <code>Reflect.apply()</code></h4>
<p>Forget the complexities of <code>Function.prototype.apply()</code>! With <code>Reflect.apply()</code>, invoking functions is a breeze.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> numbers = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>];
<span class="hljs-keyword">const</span> sum = <span class="hljs-function">(<span class="hljs-params">a, b, c</span>) =&gt;</span> a + b + c;

<span class="hljs-comment">// Using Reflect.apply()</span>
<span class="hljs-keyword">const</span> result = <span class="hljs-built_in">Reflect</span>.apply(sum, <span class="hljs-literal">null</span>, numbers);

<span class="hljs-built_in">console</span>.log(result); <span class="hljs-comment">// Output: 6</span>
</code></pre>
<h4 id="heading-2-reflectget">2️⃣. <code>Reflect.get()</code></h4>
<p>Tired of the limitations of vanilla property retrieval? <code>Reflect.get()</code> offers more control and flexibility.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> obj = { <span class="hljs-attr">x</span>: <span class="hljs-number">42</span>, <span class="hljs-attr">y</span>: <span class="hljs-string">'hello'</span> };

<span class="hljs-comment">// Using Reflect.get()</span>
<span class="hljs-keyword">const</span> value = <span class="hljs-built_in">Reflect</span>.get(obj, <span class="hljs-string">'x'</span>);

<span class="hljs-built_in">console</span>.log(value); <span class="hljs-comment">// Output: 42</span>
</code></pre>
<h4 id="heading-3-reflectset">3️⃣. <code>Reflect.set()</code></h4>
<p>Modify properties with pinpoint accuracy, even within complex object hierarchies.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> obj = { <span class="hljs-attr">x</span>: <span class="hljs-number">42</span> };

<span class="hljs-comment">// Using Reflect.set()</span>
<span class="hljs-built_in">Reflect</span>.set(obj, <span class="hljs-string">'x'</span>, <span class="hljs-number">13</span>);

<span class="hljs-built_in">console</span>.log(obj.x); <span class="hljs-comment">// Output: 13</span>
</code></pre>
<h4 id="heading-4-reflectdefineproperty">4️⃣. <code>Reflect.defineProperty()</code></h4>
<p>Defining properties with their descriptors has never been easier!</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> obj = {};

<span class="hljs-comment">// Using Reflect.defineProperty()</span>
<span class="hljs-built_in">Reflect</span>.defineProperty(obj, <span class="hljs-string">'x'</span>, { <span class="hljs-attr">value</span>: <span class="hljs-number">42</span>, <span class="hljs-attr">writable</span>: <span class="hljs-literal">false</span> });

<span class="hljs-built_in">console</span>.log(obj.x); <span class="hljs-comment">// Output: 42</span>
</code></pre>
<h4 id="heading-5-reflectdeleteproperty">5️⃣. <code>Reflect.deleteProperty()</code></h4>
<p>Wipe properties off the face of your object as if they never existed.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> obj = { <span class="hljs-attr">x</span>: <span class="hljs-number">42</span> };

<span class="hljs-comment">// Using Reflect.deleteProperty()</span>
<span class="hljs-built_in">Reflect</span>.deleteProperty(obj, <span class="hljs-string">'x'</span>);

<span class="hljs-built_in">console</span>.log(<span class="hljs-string">'x'</span> <span class="hljs-keyword">in</span> obj); <span class="hljs-comment">// Output: false</span>
</code></pre>
<h4 id="heading-6-reflectownkeys">6️⃣. <code>Reflect.ownKeys()</code></h4>
<p>Discover all the keys an object owns, including Symbols!</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> obj = { <span class="hljs-attr">x</span>: <span class="hljs-number">42</span>, [<span class="hljs-built_in">Symbol</span>(<span class="hljs-string">'key'</span>)]: <span class="hljs-string">'symbolValue'</span> };

<span class="hljs-comment">// Using Reflect.ownKeys()</span>
<span class="hljs-keyword">const</span> keys = <span class="hljs-built_in">Reflect</span>.ownKeys(obj);

<span class="hljs-built_in">console</span>.log(keys); <span class="hljs-comment">// Output: ['x', Symbol(key)]</span>
</code></pre>
<h3 id="heading-why-use-reflect">🚀 <strong>Why Use Reflect?</strong></h3>
<p>By now, you might be asking yourself, "Why should I dive into <code>Reflect</code> when there are other ways to manipulate and inspect JavaScript objects?" Great question! Let's unravel the reasons that make <code>Reflect</code> a powerful tool in your JavaScript arsenal.</p>
<h4 id="heading-1-functional-paradigm">1️⃣ <strong>Functional Paradigm</strong></h4>
<p>The <code>Reflect</code> API offers static methods that embrace the functional programming paradigm, making them first-class citizens that you can pass around in your code.</p>
<p>👉 <strong>Example:</strong></p>
<p>Suppose you want to make property retrieval generic. You can do so with ease.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> genericGet = <span class="hljs-built_in">Reflect</span>.get;
<span class="hljs-keyword">const</span> value = genericGet(someObject, <span class="hljs-string">'someProperty'</span>);
</code></pre>
<h4 id="heading-2-enhanced-error-handling">2️⃣ <strong>Enhanced Error Handling</strong></h4>
<p>Unlike methods in the <code>Object</code> API that often throw errors, <code>Reflect</code> methods return a Boolean to indicate success or failure, allowing for more elegant error handling.</p>
<p>👉 <strong>Example:</strong></p>
<p>With <code>Reflect.set()</code>, you can check if a property was set successfully and proceed accordingly.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">if</span> (<span class="hljs-built_in">Reflect</span>.set(obj, <span class="hljs-string">'key'</span>, <span class="hljs-string">'value'</span>)) {
    <span class="hljs-comment">// Property was set successfully</span>
} <span class="hljs-keyword">else</span> {
    <span class="hljs-comment">// Failed to set the property</span>
}
</code></pre>
<h4 id="heading-3-proxy-integration">3️⃣ <strong>Proxy Integration</strong></h4>
<p><code>Reflect</code> and <code>Proxy</code> are like two peas in a pod. The methods available in <code>Reflect</code> align perfectly with <code>Proxy</code> traps, allowing for seamless and straightforward custom behaviors.</p>
<p>👉 <strong>Example:</strong></p>
<p>Creating a logging proxy becomes ridiculously simple.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> handler = {
    get(target, property) {
        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Reading property: <span class="hljs-subst">${property}</span>`</span>);
        <span class="hljs-keyword">return</span> <span class="hljs-built_in">Reflect</span>.get(target, property);
    }
};
<span class="hljs-keyword">const</span> proxy = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Proxy</span>(someObject, handler);
</code></pre>
<h4 id="heading-4-consistency-and-predictability">4️⃣ <strong>Consistency and Predictability</strong></h4>
<p>Methods in <code>Reflect</code> offer a more consistent API. They always return values (often Booleans) instead of throwing errors, and the parameter orders are predictable, leading to cleaner and more maintainable code.</p>
<p>👉 <strong>Example:</strong></p>
<p>Both <code>Reflect.get()</code> and <code>Reflect.set()</code> have consistent argument ordering: <code>target, propertyKey[, receiver]</code>.</p>
<pre><code class="lang-javascript"><span class="hljs-built_in">Reflect</span>.get(target, property);
<span class="hljs-built_in">Reflect</span>.set(target, property, value);
</code></pre>
<h4 id="heading-5-intuitive-and-self-documenting">5️⃣ <strong>Intuitive and Self-Documenting</strong></h4>
<p><code>Reflect</code> methods are often more intuitive and self-documenting than their <code>Object</code> counterparts. This readability makes it easier for developers, new and experienced alike, to understand the code.</p>
<p>👉 <strong>Example:</strong></p>
<p>Compare <code>Reflect.ownKeys(obj)</code> with <code>Object.getOwnPropertyNames(obj).concat(Object.getOwnPropertySymbols(obj))</code>.</p>
<p>Which one do you find more intuitive?</p>
<h4 id="heading-6-future-proofing">6️⃣ <strong>Future-Proofing</strong></h4>
<p>As JavaScript evolves, new methods are more likely to be added to the <code>Reflect</code> API, making it a wise choice for long-term projects.</p>
<p>For more info don't waste my YouTube video on my <a target="_blank" href="https://www.youtube.com/@Puppo_92"><strong>YouTube Channel</strong></a>.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://www.youtube.com/watch?v=gaCvSu3ncbw">https://www.youtube.com/watch?v=gaCvSu3ncbw</a></div>
<p> </p>
<h3 id="heading-conclusion"><strong>Conclusion</strong></h3>
<p>And just like that, we've come to the end of our magical journey through the labyrinthine world of JavaScript's <code>Reflect</code> API! You're now armed with the tools, tricks, and spells—err methods—to perform object manipulation wizardry that would make Dumbledore proud.</p>
<p>Ready to cast your own spells? Grab your keyboard wand, and let's make the JavaScript realm a little more enchanted, one <code>Reflect</code> method at a time!</p>
<p>Remember, the magic isn’t just in the code; it’s in you, the coding sorcerer who brings it to life. Until our next spellbinding adventure, code on, wizards! 🚀✨</p>
<p><em>You can find the code of this article</em> <a target="_blank" href="https://github.com/Puppo/javascript-you-dont-know/tree/08-reflect-api"><em>here</em></a></p>
]]></content:encoded></item><item><title><![CDATA[Cracking the JavaScript Code: Unveil the Magic of Object Property Descriptors]]></title><description><![CDATA[👋 Hey, JavaScript developers!
Ever wondered what makes your objects tick? Or how to go all "Inception" on your JavaScript code by manipulating object properties at a deeper, more granular level? Well, you're in luck! Today, we're diving into the mag...]]></description><link>https://blog.delpuppo.net/cracking-the-javascript-code-unveil-the-magic-of-object-property-descriptors</link><guid isPermaLink="true">https://blog.delpuppo.net/cracking-the-javascript-code-unveil-the-magic-of-object-property-descriptors</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[js]]></category><category><![CDATA[Objects]]></category><category><![CDATA[descriptor]]></category><dc:creator><![CDATA[Luca Del Puppo]]></dc:creator><pubDate>Thu, 02 Nov 2023 06:35:07 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1699107816121/e8e2d5da-3c3e-4cfb-91d8-8cf04c5ca6ba.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>👋 Hey, JavaScript developers!</p>
<p>Ever wondered what makes your objects tick? Or how to go all "Inception" on your JavaScript code by manipulating object properties at a deeper, more granular level? Well, you're in luck! Today, we're diving into the magical world of Object Property Descriptors in JavaScript—a realm where you become the puppet master of your objects. 🎭</p>
<p>Get ready for a roller coaster ride that takes you through the hidden alleys of JavaScript's objects. By the end of this post, you'll be wielding Object Property Descriptors like a wizard casting spells, giving you full control over properties, and even the behaviour of your objects. 🧙‍♂️</p>
<h2 id="heading-what-is-a-javascript-object-property-descriptor">What is a JavaScript Object Property Descriptor?</h2>
<p>In JavaScript, objects are more than just key-value pairs. They're intricate entities with characteristics that often go unnoticed, hidden beneath the surface like an iceberg in an ocean of code. Welcome to the fascinating realm of Object Property Descriptors, a tool that lets you truly tap into the full potential of JavaScript objects.</p>
<p>An Object Property Descriptor is essentially a metadata object that details how a property on an object behaves. It's like the DNA of the property, encoding its attributes and defining its characteristics. You can think of an Object Property Descriptor as a control panel, giving you knobs and levers to fine-tune how a property can be accessed, modified, enumerated, or deleted.</p>
<p>Here are the attributes you can configure with an Object Property Descriptor:</p>
<ul>
<li><p><code>value</code>: The actual value of the property. Simple enough, right? 📦</p>
</li>
<li><p><code>writable</code>: Determines if the property value can be changed. It's like a lock that you can engage or disengage at will. 🔒</p>
</li>
<li><p><code>enumerable</code>: Controls whether the property shows up during enumeration, like when you use a <code>for...in</code> loop or <code>Object.keys()</code>. It's like a spotlight—or lack thereof—on your property. 🔦</p>
</li>
<li><p><code>configurable</code>: Decides if the property can be deleted or has its attributes changed. Think of it as the ultimate veto power. 🛑</p>
</li>
</ul>
<p>You can access and modify these attributes using built-in JavaScript methods like <code>Object.getOwnPropertyDescriptor()</code>, <code>Object.defineProperty()</code>, and <code>Object.defineProperties()</code>. These are your magic wands to perform spellbinding feats of object manipulation!</p>
<p>For example, to make a property read-only, you can set its <code>writable</code> attribute to <code>false</code>. Or if you want to hide a property from enumeration, just set the <code>enumerable</code> attribute to <code>false</code>. It’s like tailoring your object properties to fit your exact needs, almost as if you’re crafting a bespoke suit!</p>
<h2 id="heading-object-property-descriptors-in-practice"><strong>Object</strong> Property <strong>Descriptors in Practice</strong></h2>
<p>It's time to get our hands dirty and jump into the practical aspects of using Object Property Descriptors in JavaScript.</p>
<h4 id="heading-1-accessing-descriptors-with-objectgetownpropertydescriptor">1️⃣ Accessing Descriptors with <code>Object.getOwnPropertyDescriptor()</code></h4>
<p>Let's start with the basics. Ever wondered what the descriptor of an existing object property looks like? <code>Object.getOwnPropertyDescriptor()</code> is your answer. It takes two arguments: the object itself and the property name as a string.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> myObj = { <span class="hljs-attr">age</span>: <span class="hljs-number">30</span> };
<span class="hljs-keyword">const</span> descriptor = <span class="hljs-built_in">Object</span>.getOwnPropertyDescriptor(myObj, <span class="hljs-string">'age'</span>);

<span class="hljs-built_in">console</span>.log(descriptor); <span class="hljs-comment">// Output: { value: 30, writable: true, enumerable: true, configurable: true }</span>
</code></pre>
<p>Here, the <code>descriptor</code> object shows the default attributes: <code>value</code>, <code>writable</code>, <code>enumerable</code>, and <code>configurable</code>. No surprises, everything is set to <code>true</code> by default! 🎉</p>
<h4 id="heading-2-defining-descriptors-with-objectdefineproperty">2️⃣ Defining Descriptors with <code>Object.defineProperty()</code></h4>
<p>Okay, ready to step it up? What if you want to create a property with custom attributes? Say hello to <code>Object.defineProperty()</code>. It takes three arguments: the object, the property name, and the descriptor object.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> person = {};
<span class="hljs-built_in">Object</span>.defineProperty(
    person,
    <span class="hljs-string">'name'</span>,
    {
        <span class="hljs-attr">value</span>: <span class="hljs-string">'Alice'</span>,
        <span class="hljs-attr">writable</span>: <span class="hljs-literal">false</span>,
        <span class="hljs-attr">enumerable</span>: <span class="hljs-literal">true</span>,
        <span class="hljs-attr">configurable</span>: <span class="hljs-literal">false</span>
    }
);

<span class="hljs-built_in">console</span>.log(person.name); <span class="hljs-comment">// Output: Alice</span>
</code></pre>
<p>Now, <a target="_blank" href="http://person.name"><code>person.name</code></a> is read-only and not configurable but still enumerable. Try changing its value, and JavaScript will be like, "Nice try, buddy!" 🤨</p>
<h4 id="heading-3-batch-operation-with-objectdefineproperties">3️⃣ Batch Operation with <code>Object.defineProperties()</code></h4>
<p>But wait, there's more! What if you want to define multiple properties at once? <code>Object.defineProperties()</code> has got your back.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> animal = {};
<span class="hljs-built_in">Object</span>.defineProperties(animal, {
    <span class="hljs-attr">name</span>: {
        <span class="hljs-attr">value</span>: <span class="hljs-string">'Dog'</span>,
        <span class="hljs-attr">writable</span>: <span class="hljs-literal">true</span>
    },
    <span class="hljs-attr">sound</span>: {
        <span class="hljs-attr">value</span>: <span class="hljs-string">'Woof'</span>,
        <span class="hljs-attr">enumerable</span>: <span class="hljs-literal">false</span>
    }
});
</code></pre>
<p>Here, <code>animal</code> gets two properties, each with its own set of descriptors. Efficient, isn't it? 🤓</p>
<h4 id="heading-4-computed-property-with-objectdefineproperty">4️⃣ Computed property with <code>Object.defineProperty()</code></h4>
<p>But wait, there's more again. What if you want to define a property that depends on other ones? <code>Object.defineProperty()</code> has got your back again.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> person = {
  <span class="hljs-attr">firstName</span>: <span class="hljs-string">'John'</span>,
  <span class="hljs-attr">lastName</span>: <span class="hljs-string">'Doe'</span>,
};

<span class="hljs-comment">// Define a read-only property</span>
<span class="hljs-built_in">Object</span>.defineProperty(person, <span class="hljs-string">'fullName'</span>, {
  get() {
    <span class="hljs-keyword">return</span> <span class="hljs-string">`<span class="hljs-subst">${<span class="hljs-built_in">this</span>.firstName}</span> <span class="hljs-subst">${<span class="hljs-built_in">this</span>.lastName}</span>`</span>;
  },
  <span class="hljs-attr">enumerable</span>: <span class="hljs-literal">true</span>,
});

<span class="hljs-built_in">console</span>.log(person.fullName); <span class="hljs-comment">// John Doe</span>
</code></pre>
<p>Here <code>person</code> has three properties, <code>firstName</code>, <code>lastName</code> and <code>fullName</code>. <code>fullName</code> depends on the others and it's enumerable so that it's included in the <code>for...in</code> loop and <code>Object.keys()</code> method.</p>
<p>Ok, I think the idea now it's clear and you can use your imagination to combine these configurations to provide the best descriptors for your objects.</p>
<p>To find out more don't waste my YouTube video on my <a target="_blank" href="https://www.youtube.com/@Puppo_92">YouTube Channel</a></p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://www.youtube.com/watch?v=AHLdUs8LtIA">https://www.youtube.com/watch?v=AHLdUs8LtIA</a></div>
<p> </p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In conclusion, Object Property Descriptors are a powerful feature of JavaScript that allows you to manipulate and define object properties with fine-grained control. This advanced feature offers developers the ability to create more dynamic and flexible code.</p>
<p>Whether you're a junior developer or an expert, understanding Object Property Descriptors can help you level up your JavaScript skills.</p>
<p>So go ahead, tinker with your code, challenge the norms, and keep pushing the boundaries. The JavaScript universe is your playground! 🚀</p>
<p>You can find the code of this article <a target="_blank" href="https://github.com/Puppo/javascript-you-dont-know/tree/07-object-descriptor">here</a>.</p>
]]></content:encoded></item><item><title><![CDATA[JavaScript FinalizationRegistry Unraveled: Memory Management Magic Explained!]]></title><description><![CDATA[Introduction
JavaScript's memory management can be tricky, especially when it comes to handling objects that are no longer needed. As developers, we often need to deal with memory leaks and other issues that arise from improper garbage collection. Fo...]]></description><link>https://blog.delpuppo.net/javascript-finalizationregistry-unraveled-memory-management-magic-explained</link><guid isPermaLink="true">https://blog.delpuppo.net/javascript-finalizationregistry-unraveled-memory-management-magic-explained</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[js]]></category><category><![CDATA[FinalizationRegistry]]></category><dc:creator><![CDATA[Luca Del Puppo]]></dc:creator><pubDate>Wed, 25 Oct 2023 06:21:41 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1697439325296/ca379344-f66f-4519-8820-455085d972c7.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-introduction">Introduction</h2>
<p>JavaScript's memory management can be tricky, especially when it comes to handling objects that are no longer needed. As developers, we often need to deal with memory leaks and other issues that arise from improper garbage collection. Fortunately, JavaScript has introduced a new feature called the FinalizationRegistry to help us manage memory more efficiently. In this blog post, we'll dive deep into the world of FinalizationRegistry, exploring its purpose, how to use it, and real-world scenarios where it can come in handy.</p>
<h2 id="heading-a-simple-example">A Simple Example</h2>
<p>To begin, let's take a look at a simple example to understand how FinalizationRegistry works. The FinalizationRegistry is an object that enables you to register a callback function that will be invoked when an object is garbage collected. Here's a basic example:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> registry = <span class="hljs-keyword">new</span> FinalizationRegistry(<span class="hljs-function">(<span class="hljs-params">heldValue</span>) =&gt;</span> {
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Clean up: <span class="hljs-subst">${heldValue}</span>`</span>);
});

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">createObject</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> obj = {<span class="hljs-attr">id</span>: <span class="hljs-number">1</span>};
  registry.register(obj, <span class="hljs-string">"Object 1"</span>);
}

createObject();
<span class="hljs-comment">// After some time, when the object is garbage collected, the console will log: "Clean up: Object 1"</span>
</code></pre>
<p>In this example, we create a new FinalizationRegistry and provide a callback function that logs a message when the registered object is garbage collected. We then create an object and register it with the registry.</p>
<h2 id="heading-real-world-scenario">Real-World Scenario</h2>
<p>Now, let's explore a more realistic scenario where FinalizationRegistry can be beneficial. Imagine we have a web application that allows users to upload and manipulate images. We use a third-party library to handle the image manipulation, and this library creates large objects that consume a significant amount of memory. To prevent memory leaks, we can use FinalizationRegistry to ensure that these objects are properly cleaned up when they are no longer needed.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> imageRegistry = <span class="hljs-keyword">new</span> FinalizationRegistry(<span class="hljs-function">(<span class="hljs-params">imageData</span>) =&gt;</span> {
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Cleaning up image data: <span class="hljs-subst">${imageData}</span>`</span>);
  <span class="hljs-comment">// Perform additional cleanup tasks, such as releasing resources associated with imageData</span>
});

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">loadImage</span>(<span class="hljs-params">imageUrl</span>) </span>{
  <span class="hljs-keyword">return</span> fetch(imageUrl)
    .then(<span class="hljs-function">(<span class="hljs-params">response</span>) =&gt;</span> response.blob())
    .then(<span class="hljs-function">(<span class="hljs-params">imageBlob</span>) =&gt;</span> {
      <span class="hljs-keyword">const</span> imageData = <span class="hljs-keyword">new</span> ImageData(imageBlob);
      imageRegistry.register(imageData, <span class="hljs-string">`Image: <span class="hljs-subst">${imageUrl}</span>`</span>);
      <span class="hljs-keyword">return</span> imageData;
    });
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">manipulateImage</span>(<span class="hljs-params">imageData</span>) </span>{
  <span class="hljs-comment">// Use the third-party library to manipulate the image</span>
}

loadImage(<span class="hljs-string">'https://example.com/image.jpg'</span>)
  .then(<span class="hljs-function">(<span class="hljs-params">imageData</span>) =&gt;</span> {
    manipulateImage(imageData);
    <span class="hljs-comment">// After manipulation, the imageData object will eventually be garbage collected</span>
  });
</code></pre>
<p>In this example, we create an imageRegistry using FinalizationRegistry and register the ImageData objects when they are loaded. When an ImageData object is garbage collected, the provided callback function will log a message and perform any additional cleanup tasks required.</p>
<h2 id="heading-considerations">Considerations</h2>
<p>While the FinalizationRegistry is a powerful tool for managing memory, there are some important considerations to keep in mind:</p>
<ol>
<li><p>The timing of garbage collection is not guaranteed, and the callback function may not be invoked immediately after an object becomes unreachable.</p>
</li>
<li><p>FinalizationRegistry should not be used to manage critical resources, as it only provides a best-effort cleanup mechanism.</p>
</li>
<li><p>The held values in the registry should not be used to access the registered objects, as it may prevent them from being garbage collected.</p>
</li>
</ol>
<p>To find out more don't waste my YouTube video on my <a target="_blank" href="https://www.youtube.com/@Puppo_92">YouTube channel</a></p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://www.youtube.com/watch?v=3sgIFrjA61U">https://www.youtube.com/watch?v=3sgIFrjA61U</a></div>
<p> </p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>The JavaScript FinalizationRegistry is a valuable addition to the language that can help developers manage memory more efficiently and prevent memory leaks. By understanding how it works and knowing when to use it, you can create more performant and memory-efficient applications. Keep in mind the considerations mentioned above, and happy coding!</p>
<p><em>You can find the code of this article</em> <a target="_blank" href="https://github.com/Puppo/javascript-you-dont-know/tree/06-finalizationregistry"><em>here</em></a><em>.</em></p>
]]></content:encoded></item><item><title><![CDATA[Unlocking the Power of Proxies: JavaScript's Secret Superheroes]]></title><description><![CDATA[JavaScript's Proxy object is a powerful feature that enables you to intercept and customize operations performed on objects. This versatile tool allows developers to create more efficient and flexible code while also improving code maintainability. I...]]></description><link>https://blog.delpuppo.net/unlocking-the-power-of-proxies-javascripts-secret-superheroes</link><guid isPermaLink="true">https://blog.delpuppo.net/unlocking-the-power-of-proxies-javascripts-secret-superheroes</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[js]]></category><category><![CDATA[proxy]]></category><dc:creator><![CDATA[Luca Del Puppo]]></dc:creator><pubDate>Wed, 18 Oct 2023 06:03:05 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1697438402100/dd6fa71f-5efd-413d-9af4-8f5e18f88c32.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>JavaScript's Proxy object is a powerful feature that enables you to intercept and customize operations performed on objects. This versatile tool allows developers to create more efficient and flexible code while also improving code maintainability. In this article, we will dive into the world of JavaScript proxies, explore their use cases, and provide examples for expert developers.</p>
<h2 id="heading-a-brief-introduction-to-proxies-in-javascript">A Brief Introduction to Proxies in JavaScript</h2>
<p>A Proxy object in JavaScript is used to define custom behaviour for fundamental operations such as property lookup, assignment, enumeration, and function invocation. It acts as a wrapper around another object, called the target, and allows you to intercept and manipulate operations performed on the target object.</p>
<h3 id="heading-creating-a-javascript-proxy">Creating a JavaScript Proxy</h3>
<p>To create a JavaScript Proxy, you need two things: a target object and a handler object. The target object is the object you want to wrap with the Proxy, while the handler object defines the custom behaviour for the proxy.</p>
<p>Here's a simple example of creating a Proxy:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> target = { <span class="hljs-attr">name</span>: <span class="hljs-string">"John"</span>, <span class="hljs-attr">surname</span>: <span class="hljs-string">"Doe"</span>, <span class="hljs-attr">fullName</span>: <span class="hljs-string">"John Doe"</span> };
<span class="hljs-keyword">const</span> handler = {
  get(_target, prop) {
    <span class="hljs-keyword">return</span> _target[prop] ? _target[prop].toUpperCase() : <span class="hljs-string">"Property not found"</span>;
  },
  set(_target, prop, value) {
    <span class="hljs-keyword">if</span> (prop === <span class="hljs-string">'name'</span>) {
      _target.fullName = value + <span class="hljs-string">' '</span> + _target.surname;
    }
    <span class="hljs-keyword">if</span> (prop === <span class="hljs-string">'surname'</span>) {
      _target.fullName = _target.name + <span class="hljs-string">' '</span> + value;
    }
    <span class="hljs-keyword">if</span> (prop === <span class="hljs-string">'fullName'</span>) {
      <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">'fullName is not writable'</span>)
    }
    _target[prop] = value;
    <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
  }
};

<span class="hljs-keyword">const</span> proxy = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Proxy</span>(target, handler);
<span class="hljs-built_in">console</span>.log(proxy.fullName); <span class="hljs-comment">// Output: "JOHN DOE"</span>
<span class="hljs-built_in">console</span>.log(proxy.nonexistent); <span class="hljs-comment">// Output: "Property not found"</span>
proxy.name = <span class="hljs-string">'Jane'</span>;
<span class="hljs-built_in">console</span>.log(proxy.fullName); <span class="hljs-comment">// Output: "Jane Doe"</span>
proxy.surname = <span class="hljs-string">'Smith'</span>;
<span class="hljs-built_in">console</span>.log(proxy.fullName); <span class="hljs-comment">// Output: "Jane Smith"</span>
proxy.fullName = <span class="hljs-string">'Tom Smith'</span>; <span class="hljs-comment">// Error: fullName is not writable</span>
</code></pre>
<p>In this example, we defined a <code>get</code> trap in the handler object, which intercepts the property lookup operation on the target object. When a property is accessed on the proxy object, the <code>get</code> trap is invoked, and it returns the property value in uppercase if the property exists or a custom message if it doesn't.<br />Then, we defined a <code>set</code> trap, which intercepts a property's set. If the property name is <code>name</code> or <code>surname</code> calculates the <code>fullName</code> and sets the target object with the right value, but if you try to set the <code>fullName</code> property the code raises an error.</p>
<h3 id="heading-use-cases-for-proxies-in-javascript">Use Cases for Proxies in JavaScript</h3>
<h4 id="heading-validation-and-constraints">Validation and Constraints</h4>
<p>Proxies can be used to enforce data validation and constraints when setting properties on an object. For example, you can ensure that a property value is a certain type or within a specific range.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> target = { <span class="hljs-attr">age</span>: <span class="hljs-number">25</span> };
<span class="hljs-keyword">const</span> handler = {
  set(_target, prop, value) {
    <span class="hljs-keyword">if</span> (prop === <span class="hljs-string">"age"</span> &amp;&amp; (<span class="hljs-keyword">typeof</span> value !== <span class="hljs-string">"number"</span> || value &lt; <span class="hljs-number">0</span> || value &gt; <span class="hljs-number">150</span>)) {
      <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">TypeError</span>(<span class="hljs-string">"Invalid age value"</span>);
    }
    _target[prop] = value;
    <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
  },
};

<span class="hljs-keyword">const</span> proxy = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Proxy</span>(target, handler);
proxy.age = <span class="hljs-number">30</span>; <span class="hljs-comment">// Works fine</span>
proxy.age = <span class="hljs-string">"thirty"</span>; <span class="hljs-comment">// Throws TypeError: "Invalid age value"</span>
</code></pre>
<h4 id="heading-logging-and-profiling">Logging and Profiling</h4>
<p>Proxies can be used to log and profile operations performed on an object, which can be helpful during debugging and performance analysis.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> target = { <span class="hljs-attr">message</span>: <span class="hljs-string">"Hello, World!"</span> };
<span class="hljs-keyword">const</span> handler = {
  get(_target, prop) {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Accessing property "<span class="hljs-subst">${prop}</span>"`</span>);
    <span class="hljs-keyword">return</span> _target[prop];
  },
  set(_target, prop, value) {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Setting property "<span class="hljs-subst">${prop}</span>" to "<span class="hljs-subst">${value}</span>"`</span>);
    _target[prop] = value;
    <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
  },
};

<span class="hljs-keyword">const</span> proxy = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Proxy</span>(target, handler);
<span class="hljs-built_in">console</span>.log(proxy.message); <span class="hljs-comment">// Logs: "Accessing property "message"" and outputs: "Hello, World!"</span>
proxy.message = <span class="hljs-string">"Goodbye, World!"</span>; <span class="hljs-comment">// Logs: "Setting property "message" to "Goodbye, World!""</span>
</code></pre>
<p>To learn more don't miss my YouTube video about JavaScript Proxy on my <a target="_blank" href="https://www.youtube.com/@Puppo_92">YouTube channel</a></p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://www.youtube.com/watch?v=e7_lxSrP_Ok">https://www.youtube.com/watch?v=e7_lxSrP_Ok</a></div>
<p> </p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>JavaScript's Proxy object is a powerful and versatile feature that allows developers to create more efficient and flexible code. By understanding and utilizing proxies, you can unlock their full potential and become a true JavaScript superhero.</p>
<p><em>You can find the code of this article</em> <a target="_blank" href="https://github.com/Puppo/javascript-you-dont-know/tree/05-proxies"><em>here</em></a><em>.</em></p>
]]></content:encoded></item><item><title><![CDATA[JavaScript WeakRef Explained: Harnessing Memory Management Magic]]></title><description><![CDATA[Introduction to WeakRef
WeakRef is a powerful feature in JavaScript that allows developers to create weak object references. A weak reference is a reference that does not prevent the object it refers to from being garbage collected. This can be usefu...]]></description><link>https://blog.delpuppo.net/javascript-weakref-explained-harnessing-memory-management-magic</link><guid isPermaLink="true">https://blog.delpuppo.net/javascript-weakref-explained-harnessing-memory-management-magic</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[js]]></category><category><![CDATA[ES6]]></category><category><![CDATA[weakref]]></category><dc:creator><![CDATA[Luca Del Puppo]]></dc:creator><pubDate>Wed, 11 Oct 2023 06:23:40 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1696366700726/74cd215b-87d4-4ba7-b810-2069f32cf8c1.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-introduction-to-weakref">Introduction to WeakRef</h2>
<p>WeakRef is a powerful feature in JavaScript that allows developers to create weak object references. A weak reference is a reference that does not prevent the object it refers to from being garbage collected. This can be useful when you want to maintain a reference to an object without preventing it from being cleaned up by the garbage collector.</p>
<h2 id="heading-how-weakref-works">How WeakRef Works</h2>
<p>WeakRef works by creating a weak reference to an object. This reference does not count towards the object's reference count and does not prevent it from being garbage collected. To access the object, you can call the <code>deref()</code> method on the WeakRef instance. If the object is still alive, the method will return the object; otherwise, it will return undefined.</p>
<h2 id="heading-implementing-weakref-in-your-code">Implementing WeakRef in Your Code</h2>
<p>To use WeakRef in your code, follow these steps:</p>
<ol>
<li><p>Create a new WeakRef instance by passing the object you want to reference as an argument: <code>const weakRef = new WeakRef(targetObject);</code></p>
</li>
<li><p>To access the object, call the <code>deref()</code> method on the WeakRef instance: <code>const object = weakRef.deref();</code></p>
</li>
<li><p>Check if the object is still alive by testing if it is not undefined: <code>if (object !== undefined) { /* object is still alive */ }</code></p>
</li>
</ol>
<h2 id="heading-use-cases-for-weakref">Use Cases for WeakRef</h2>
<p>WeakRef can be helpful in several scenarios, such as:</p>
<ol>
<li><p><strong>Caching</strong>:</p>
<p> Use <code>WeakRef</code> to create a cache for expensive-to-create objects. When an object is no longer needed, it can be garbage collected automatically, freeing up memory.</p>
</li>
<li><p><strong>DOM Element References</strong>:</p>
<p> In web applications, you can use <code>WeakRef</code> to hold references to DOM elements. This can help prevent memory leaks when you need to keep track of elements for event handling or manipulation.</p>
</li>
<li><p><strong>Resource Cleanup</strong>:</p>
<p> When working with external resources like files or network connections, you can use <code>WeakRef</code> to keep track of those resources. If the resource becomes unused (e.g., a file is closed or a network connection is no longer needed), it can be automatically released.</p>
</li>
<li><p><strong>Memoization</strong>:</p>
<p> Implement memoization using <code>WeakRef</code> to store the results of function calls. This allows you to cache function results without preventing the input arguments from being garbage-collected when they're no longer needed.</p>
</li>
<li><p><strong>Managing Timers</strong>:</p>
<p> When using timers (e.g., <code>setTimeout</code> or <code>setInterval</code>), you can use <code>WeakRef</code> to hold references to objects associated with the timer. This can help ensure that the timer doesn't keep objects alive longer than necessary.</p>
</li>
<li><p><strong>Event Handling</strong>:</p>
<p> In event-driven applications, you can use <code>WeakRef</code> to manage event listeners. When an object with event listeners is no longer in use, the associated event listeners can be automatically removed.</p>
</li>
<li><p><strong>Reacting to DOM Node Removal</strong>:</p>
<p> In cases where you want to perform actions when DOM nodes are removed, you can use <code>WeakRef</code> to track DOM nodes. When a node is removed from the DOM, you can receive a notification and perform cleanup tasks.</p>
</li>
<li><p><strong>Custom Data Structures</strong>:</p>
<p> Create custom data structures that use <code>WeakRef</code> to hold references to elements. This can be particularly useful in scenarios like implementing caches or data structures with automatic cleanup.</p>
</li>
<li><p><strong>Managing Web Workers</strong>:</p>
<p> When working with Web Workers, you can use <code>WeakRef</code> to manage references to worker instances. When a worker is no longer needed, its reference can be automatically released.</p>
</li>
<li><p><strong>Optimizing Memory-Intensive Applications</strong>:</p>
<p>In memory-intensive applications, you can use <code>WeakRef</code> to ensure that large data structures or objects are only kept in memory as long as they're actively used.</p>
</li>
</ol>
<h2 id="heading-best-practices-and-limitations">Best Practices and Limitations</h2>
<p>When using WeakRef, keep in mind the following best practices and limitations:</p>
<ol>
<li><p>Use WeakRef only when necessary, as it can introduce complexity and potential performance issues.</p>
</li>
<li><p>Do not rely on the timing of garbage collection, as it may vary across JavaScript engines and environments.</p>
</li>
<li><p>Be aware that WeakRef is not supported in all environments, so you may need to provide a fallback implementation or polyfill.</p>
</li>
</ol>
<p>If you want to learn more about WeakRef, don't miss out on my YouTube video on <a target="_blank" href="https://www.youtube.com/@Puppo_92">my YouTube channel</a> 🚀</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://youtu.be/-rN03KAHGC4">https://youtu.be/-rN03KAHGC4</a></div>
<p> </p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>WeakRef is a powerful feature in JavaScript that allows you to create weak references to objects, enabling you to maintain references without preventing garbage collection. By understanding how WeakRef works and its use cases, you can use memory more efficiently in your applications and avoid memory leaks.</p>
<p><a target="_blank" href="https://github.com/Puppo/javascript-you-dont-know/tree/04-weakrefs"><em>Here is</em></a> <em>the source code of this post.</em></p>
]]></content:encoded></item><item><title><![CDATA[Unlock the Power of JavaScript WeakSet: Mastering a Hidden Gem!]]></title><description><![CDATA[In the vast landscape of JavaScript, many powerful features often go unnoticed. One such hidden gem is the WeakSet, an unsung hero of the language that can help you optimize your code and manage memory more effectively. In this article, we'll dive de...]]></description><link>https://blog.delpuppo.net/unlock-the-power-of-javascript-weakset-mastering-a-hidden-gem</link><guid isPermaLink="true">https://blog.delpuppo.net/unlock-the-power-of-javascript-weakset-mastering-a-hidden-gem</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[ES6]]></category><category><![CDATA[es2015]]></category><category><![CDATA[js]]></category><category><![CDATA[weakset]]></category><dc:creator><![CDATA[Luca Del Puppo]]></dc:creator><pubDate>Wed, 04 Oct 2023 06:22:01 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1695752493733/53b5c3b1-0221-47dc-b8bd-c40ed10639e6.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In the vast landscape of JavaScript, many powerful features often go unnoticed. One such hidden gem is the WeakSet, an unsung hero of the language that can help you optimize your code and manage memory more effectively. In this article, we'll dive deep into WeakSet, uncovering their potential and learning how to use them effectively in our JavaScript projects.</p>
<h2 id="heading-a-brief-introduction-to-weakset">A Brief Introduction to WeakSet</h2>
<p>WeakSet is a collection of objects similar to the more commonly used Set.<br />However, there's a significant difference between the two: WeakSet holds only weak references to the objects stored within them. This means that if an object is only referenced by a WeakSet, it can still be garbage collected, freeing up valuable memory resources.</p>
<p>This unique feature of WeakSet makes it an excellent choice for managing certain types of data relationships, mainly when memory management is a priority.</p>
<h2 id="heading-creating-and-using-weakset">Creating and Using WeakSet</h2>
<p>To create a WeakSet, instantiate a new instance of the WeakSet class:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> weakSet = <span class="hljs-keyword">new</span> <span class="hljs-built_in">WeakSet</span>();
</code></pre>
<p>Adding objects to a WeakSet is easy. Just use the <code>add</code> method:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> obj1 = {};
<span class="hljs-keyword">const</span> obj2 = {};

weakSet.add(obj1);
weakSet.add(obj2);
</code></pre>
<p>WeakSets also provide methods for checking if an object is present (<code>has</code>) and removing objects (<code>delete</code>):</p>
<pre><code class="lang-javascript"><span class="hljs-built_in">console</span>.log(weakSet.has(obj1)); <span class="hljs-comment">// true</span>
weakSet.delete(obj1);
<span class="hljs-built_in">console</span>.log(weakSet.has(obj1)); <span class="hljs-comment">// false</span>
</code></pre>
<p>However, unlike Sets, WeakSets do not have methods for iterating over their contents or determining their size. This is because of their weakly-referenced nature, which makes it impossible to know how many objects are still being held in memory.</p>
<h2 id="heading-use-cases-for-weaksets">Use Cases for WeakSets</h2>
<h4 id="heading-1-managing-dom-elements">1. Managing DOM Elements</h4>
<p><code>WeakSet</code> can be incredibly useful when working with the DOM. You can store references to DOM elements without worrying about memory leaks. When an element is removed from the DOM, the reference in the <code>WeakSet</code> will be automatically garbage collected.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> domElements = <span class="hljs-keyword">new</span> <span class="hljs-built_in">WeakSet</span>();
<span class="hljs-keyword">const</span> element = <span class="hljs-built_in">document</span>.querySelector(<span class="hljs-string">'.my-element'</span>);
domElements.add(element);

<span class="hljs-comment">// Later, when the element is removed from the DOM</span>
domElements.has(element); <span class="hljs-comment">// false (garbage collected)</span>
</code></pre>
<h4 id="heading-2-private-data-storage">2. Private Data Storage</h4>
<p><code>WeakSet</code> can be used to store private data associated with an object without exposing it. Since the references are weak, the data will be automatically removed when the object is no longer reachable.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> privateData = <span class="hljs-keyword">new</span> <span class="hljs-built_in">WeakSet</span>();

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyClass</span> </span>{
  <span class="hljs-keyword">constructor</span>() {
    privateData.add(<span class="hljs-built_in">this</span>);
  }

  #data = <span class="hljs-string">'I am private data'</span>;

  getData() {
    <span class="hljs-keyword">if</span> (privateData.has(<span class="hljs-built_in">this</span>)) {
      <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.#data;
    }
    <span class="hljs-keyword">return</span> <span class="hljs-literal">undefined</span>;
  }
}
</code></pre>
<p>To see WeakSets in action, don't waste the opportunity to look at my YouTube video about them.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://youtu.be/m3BKqgeVAa4">https://youtu.be/m3BKqgeVAa4</a></div>
<p> </p>
<h2 id="heading-in-conclusion">In Conclusion</h2>
<p>WeakSet may not be the most well-known feature of JavaScript, but it offers unique capabilities that can be invaluable in certain situations. By understanding and embracing WeakSet, you can optimize your code, enhance memory management, and unlock the full potential of this hidden gem in the JavaScript universe.</p>
<p>You can find the source code <a target="_blank" href="https://github.com/Puppo/javascript-you-dont-know/tree/03-weaksets">here</a></p>
]]></content:encoded></item><item><title><![CDATA[Unlocking JavaScript's Secret Weapon: The Power of WeakMaps]]></title><description><![CDATA[Introduction
JavaScript is a powerful and versatile programming language that has evolved over the years, introducing new features and improvements to enhance its performance and capabilities. One such feature is the WeakMap, a collection of key-valu...]]></description><link>https://blog.delpuppo.net/unlocking-javascripts-secret-weapon-the-power-of-weakmaps</link><guid isPermaLink="true">https://blog.delpuppo.net/unlocking-javascripts-secret-weapon-the-power-of-weakmaps</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[ES6]]></category><category><![CDATA[weakmap]]></category><dc:creator><![CDATA[Luca Del Puppo]]></dc:creator><pubDate>Wed, 27 Sep 2023 05:50:43 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1695746894241/554dfac7-1e8d-4b3a-bb70-242ace2b6456.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-introduction">Introduction</h2>
<p>JavaScript is a powerful and versatile programming language that has evolved over the years, introducing new features and improvements to enhance its performance and capabilities. One such feature is the WeakMap, a collection of key-value pairs that offers unique benefits regarding memory management and data privacy. This article will delve into the world of WeakMap in JavaScript, exploring their creation, usage, limitations, and real-world applications.</p>
<h2 id="heading-understanding-weakmap">Understanding WeakMap</h2>
<p>In JavaScript, a WeakMap is a type of Map that holds key-value pairs where the keys are objects, and the values can be any arbitrary data. The primary difference between a Map and a WeakMap is how they manage memory management. In a WeakMap, when a key object becomes inaccessible, the entry is automatically removed, allowing the garbage collector to reclaim memory efficiently.</p>
<h2 id="heading-creating-and-using-weakmap">Creating and Using WeakMap</h2>
<p>To create a new WeakMap, use the <code>new WeakMap()</code> constructor. Once created, you can set values for the keys using the <code>set</code> method, as shown below:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> weakmap = <span class="hljs-keyword">new</span> <span class="hljs-built_in">WeakMap</span>();
<span class="hljs-keyword">const</span> key = { <span class="hljs-attr">name</span>: <span class="hljs-string">"John Doe"</span> };
weakmap.set(key, <span class="hljs-string">"Some value"</span>);
</code></pre>
<p>To retrieve values associated with keys, use the <code>get</code> method:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> value = weakmap.get(key); <span class="hljs-comment">// "Some value"</span>
</code></pre>
<p>You can remove entries from the WeakMap using the <code>delete</code> method and check for the existence of a key using the <code>has</code> method:</p>
<pre><code class="lang-javascript">weakmap.delete(key); <span class="hljs-comment">// true</span>
weakmap.has(key); <span class="hljs-comment">// false</span>
</code></pre>
<h2 id="heading-practical-applications-of-weakmap">Practical Applications of WeakMap</h2>
<p>WeakMap offers several practical applications in JavaScript:</p>
<ol>
<li><p>Privacy and Encapsulation: By storing private data separately from the object, WeakMap can enhance privacy and encapsulation. This is particularly useful for classes and objects where internal data should not be exposed to the outside world.</p>
</li>
<li><p>Memory Management: WeakMap automatically releases unreferenced keys and associated values, allowing for efficient memory management in large applications.</p>
</li>
<li><p>Caching: WeakMap can implement caching mechanisms without causing memory leaks, as they automatically remove entries when keys are no longer accessible.</p>
</li>
</ol>
<h2 id="heading-limitations-of-weakmap">Limitations of WeakMap</h2>
<p>Despite their benefits, WeakMap has some limitations:</p>
<ol>
<li><p>Keys must be objects: Unlike Maps, WeakMap requires keys to be objects, not primitive values.</p>
</li>
<li><p>No built-in iteration methods: WeakMap does not have built-in methods for iterating over their entries, such as <code>forEach</code> or <code>entries</code>.</p>
</li>
<li><p>No <code>clear</code> method: There is no built-in method to clear the entire WeakMap.</p>
</li>
<li><p>Limited compatibility: WeakMap is not supported in some older browsers, limiting their compatibility.</p>
</li>
</ol>
<h2 id="heading-real-world-examples-and-use-cases">Real-world Examples and Use Cases</h2>
<p>WeakMap can be utilized in various real-world scenarios:</p>
<ol>
<li><p>Event Listeners: When managing event listeners in DOM elements, WeakMap can help prevent memory leaks by automatically removing entries when elements are no longer accessible.</p>
</li>
<li><p>Private Data Storage: WeakMap can store private data in classes and objects, ensuring that internal data is not exposed to the outside world.</p>
</li>
<li><p>Large Applications: WeakMap can optimize memory usage in large applications by automatically releasing unreferenced data, improving performance and reducing memory leaks.</p>
</li>
</ol>
<p><em>To find out more about WeakMap don't miss out on my Youtube video on my</em> <a target="_blank" href="https://www.youtube.com/@puppo_92"><em>Youtube channel</em></a><em>.</em></p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://youtu.be/8Z4ZYDSxN3A">https://youtu.be/8Z4ZYDSxN3A</a></div>
<p> </p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In conclusion, WeakMap offers powerful features and applications for efficient memory management and data privacy in JavaScript. While they have some limitations, their benefits often outweigh these drawbacks, making them a valuable addition to a JavaScript developer's toolkit. As the language continues to evolve, future developments will likely address these limitations and further improve the usefulness of WeakMap in JavaScript applications.</p>
<p><em>The code of this article is available</em> <a target="_blank" href="https://github.com/Puppo/javascript-you-dont-know/tree/02-weakmaps"><em>here</em></a></p>
]]></content:encoded></item><item><title><![CDATA[Unveiling the Magic: Exploring JavaScript Symbols]]></title><description><![CDATA[Introduction to JavaScript Symbols
JavaScript Symbols are a new primitive data type introduced in ECMAScript 6 (ES6). They are used as unique, non-string identifiers for object properties, useful in avoiding naming collisions and enabling more advanc...]]></description><link>https://blog.delpuppo.net/unveiling-the-magic-exploring-javascript-symbols</link><guid isPermaLink="true">https://blog.delpuppo.net/unveiling-the-magic-exploring-javascript-symbols</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[js]]></category><category><![CDATA[ES6]]></category><dc:creator><![CDATA[Luca Del Puppo]]></dc:creator><pubDate>Wed, 20 Sep 2023 06:09:44 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1695190078887/fe1f3f4e-a1e9-446f-8a6c-4d40c5f8ae01.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-introduction-to-javascript-symbols">Introduction to JavaScript Symbols</h2>
<p>JavaScript Symbols are a new primitive data type introduced in ECMAScript 6 (ES6). They are used as unique, non-string identifiers for object properties, useful in avoiding naming collisions and enabling more advanced programming techniques.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://youtu.be/o8YDHAS-fo0">https://youtu.be/o8YDHAS-fo0</a></div>
<p> </p>
<h2 id="heading-creating-and-understanding-symbols">Creating and Understanding Symbols</h2>
<p>Symbols are created using the <code>Symbol()</code> function, which can take an optional description as an argument. Each symbol is unique; even if two symbols have the same description, they are considered distinct.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> propSymbol = <span class="hljs-built_in">Symbol</span>(<span class="hljs-string">"propName"</span>);
<span class="hljs-keyword">const</span> propSymbol2 = <span class="hljs-built_in">Symbol</span>(<span class="hljs-string">"propName"</span>);

propSymbol === propSymbol2 <span class="hljs-comment">// false</span>
</code></pre>
<h2 id="heading-unique-identifiers-and-property-keys">Unique Identifiers and Property Keys</h2>
<p>Symbols are often used as property keys in objects to ensure uniqueness and prevent naming collisions. They can be used alongside string keys without conflict, and their uniqueness makes them ideal for use as metadata or private properties in objects.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> propSymbol = <span class="hljs-built_in">Symbol</span>(<span class="hljs-string">"propName"</span>);
<span class="hljs-keyword">const</span> propSymbol2 = <span class="hljs-built_in">Symbol</span>(<span class="hljs-string">"propName"</span>);

<span class="hljs-keyword">const</span> obj = {
  [propSymbol]: <span class="hljs-string">"propSymbol"</span>,
  [propSymbol2]: <span class="hljs-string">"propSymbol2"</span>
}
</code></pre>
<h2 id="heading-the-global-symbol-registry">The Global Symbol Registry</h2>
<p>The global Symbol registry allows you to create and share symbols across different scopes and realms. To create a global symbol, use <code>Symbol.for(key)</code>, which takes a string as its argument. This method checks if a symbol with the same key exists in the registry; if not, it creates a new one.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// my-module-1.js</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> propSymbol = <span class="hljs-built_in">Symbol</span>(<span class="hljs-string">"propName"</span>);
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> propSymbolShare = <span class="hljs-built_in">Symbol</span>.for(<span class="hljs-string">"propName"</span>);

<span class="hljs-comment">// my-module-2.js</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> propSymbol = <span class="hljs-built_in">Symbol</span>(<span class="hljs-string">"propName"</span>);
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> propSymbolShare = <span class="hljs-built_in">Symbol</span>.for(<span class="hljs-string">"propName"</span>);

<span class="hljs-comment">// index.js</span>
<span class="hljs-keyword">import</span> { propSymbol <span class="hljs-keyword">as</span> propSymbolM1, propSymbolShare <span class="hljs-keyword">as</span> propSymbolShareM1 } <span class="hljs-keyword">from</span> <span class="hljs-string">'./my-module.js'</span>
<span class="hljs-keyword">import</span> { propSymbol <span class="hljs-keyword">as</span> propSymbolM2, propSymbolShare <span class="hljs-keyword">as</span> propSymbolShareM2 } <span class="hljs-keyword">from</span> <span class="hljs-string">'./my-module-2.js'</span>

<span class="hljs-built_in">console</span>.log(propSymbolM1 === propSymbolM2); <span class="hljs-comment">// false</span>

<span class="hljs-built_in">console</span>.log(propSymbolM1 === propSymbolShareM1); <span class="hljs-comment">// false</span>
<span class="hljs-built_in">console</span>.log(propSymbolM2 === propSymbolShareM2); <span class="hljs-comment">// false</span>

<span class="hljs-built_in">console</span>.log(propSymbolShareM1 === propSymbolShareM2); <span class="hljs-comment">// true</span>
</code></pre>
<p>It's also possible to retrieve the key of a Symbol using <code>Symbol.keyFor(key)</code> but only for shared keys.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> propSymbol = <span class="hljs-built_in">Symbol</span>(<span class="hljs-string">"propName"</span>);
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> propSymbolShare = <span class="hljs-built_in">Symbol</span>.for(<span class="hljs-string">"propName"</span>);

<span class="hljs-built_in">console</span>.log(<span class="hljs-built_in">Symbol</span>.keyFor(propSymbol)); <span class="hljs-comment">// undefined</span>
<span class="hljs-built_in">console</span>.log(<span class="hljs-built_in">Symbol</span>.keyFor(propSymbolShare)); <span class="hljs-comment">// propName</span>
</code></pre>
<h2 id="heading-symbols-and-iteration">Symbols and Iteration</h2>
<p>Symbols are not enumerable, which means they are not included in standard iteration methods like <code>for...in</code> loops or <code>Object.keys()</code>. To access an object's symbol properties, use <code>Object.getOwnPropertySymbols()</code>.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> propSymbol = <span class="hljs-built_in">Symbol</span>(<span class="hljs-string">"propName"</span>);
<span class="hljs-keyword">const</span> propSymbol2 = <span class="hljs-built_in">Symbol</span>(<span class="hljs-string">"propName"</span>);

<span class="hljs-keyword">const</span> obj = {
  [propSymbol]: <span class="hljs-string">"propSymbol"</span>,
  [propSymbol2]: <span class="hljs-string">"propSymbol2"</span>
}
<span class="hljs-built_in">console</span>.log(<span class="hljs-built_in">JSON</span>.stringify(obj)); <span class="hljs-comment">// {}</span>
<span class="hljs-built_in">console</span>.log(<span class="hljs-built_in">Object</span>.keys(obj)); <span class="hljs-comment">// []</span>
<span class="hljs-built_in">console</span>.log(<span class="hljs-built_in">Object</span>.getOwnPropertyNames(obj)); <span class="hljs-comment">// []</span>
<span class="hljs-keyword">for</span> (<span class="hljs-keyword">const</span> key <span class="hljs-keyword">in</span> obj) {
  <span class="hljs-built_in">console</span>.log(key); <span class="hljs-comment">// nothing</span>
}

<span class="hljs-built_in">console</span>.log(<span class="hljs-built_in">Object</span>.getOwnPropertySymbols(obj)); <span class="hljs-comment">// [ Symbol(propName), Symbol(propName) ]</span>
</code></pre>
<h2 id="heading-well-known-symbols-in-javascript">Well-Known Symbols in JavaScript</h2>
<p>Well-known symbols are predefined global symbols that represent common behaviours in JavaScript, such as <code>Symbol.iterator</code>, <code>Symbol.asyncIterator</code>, <code>Symbol.toStringTag</code>, and <code>Symbol.species</code>. These symbols can be used to customize the behaviour of built-in JavaScript objects and classes.</p>
<h2 id="heading-use-cases-and-practical-applications">Use Cases and Practical Applications</h2>
<p>Symbols can be used to implement private properties, metadata, or methods, avoiding naming collisions in libraries and frameworks. They are also used to customize the behaviour of well-known JavaScript objects and classes, such as iterators and string conversion.</p>
<h2 id="heading-limitations-and-considerations">Limitations and Considerations</h2>
<p>Symbols are not supported in older JavaScript environments, and their unique nature may require additional care when working with serialization or proxy objects. Additionally, they are not directly accessible during iteration, which may require extra steps to access their properties.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>JavaScript Symbols provide a powerful, unique identifier for object properties, helping to avoid naming collisions and enabling advanced programming techniques. Understanding their use cases and limitations is essential for modern JavaScript developers.</p>
<p><em>You can find the source code</em> <a target="_blank" href="https://github.com/Puppo/javascript-you-dont-know/tree/01-symbols"><em>here</em></a></p>
]]></content:encoded></item><item><title><![CDATA[JavaScript Async Generators Unleashed: Harnessing Asynchronous Power]]></title><description><![CDATA[In the dynamic realm of JavaScript, the ability to efficiently handle asynchronous operations is paramount for building responsive and robust applications. While Async Iterators have already proven their worth in managing asynchronous data streams, J...]]></description><link>https://blog.delpuppo.net/javascript-async-generators-unleashed-harnessing-asynchronous-power</link><guid isPermaLink="true">https://blog.delpuppo.net/javascript-async-generators-unleashed-harnessing-asynchronous-power</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[js]]></category><category><![CDATA[asynchronous]]></category><category><![CDATA[generators]]></category><dc:creator><![CDATA[Luca Del Puppo]]></dc:creator><pubDate>Fri, 15 Sep 2023 06:00:11 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1693134246282/ca146f71-088a-45df-a914-a323c2c8287a.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In the dynamic realm of JavaScript, the ability to efficiently handle asynchronous operations is paramount for building responsive and robust applications. While Async Iterators have already proven their worth in managing asynchronous data streams, JavaScript takes another leap forward with Async Generators. Imagine a world where you can effortlessly produce a continuous stream of asynchronous data while dynamically controlling its flow. This is precisely where Async Generators excel, revolutionizing the way we handle and manipulate asynchronous sequences.</p>
<p>In this blog post, we're diving deep into the captivating world of JavaScript Async Generators. We'll unveil how Async Generators empower developers to create elegant solutions for complex asynchronous scenarios. Whether you're grappling with real-time data synchronization, asynchronous data processing, or any scenario demanding fine-tuned control over data flow, join us on this journey as we unravel the capabilities, nuances, and transformative power of JavaScript Async Generators.</p>
<p>Before we delve into Async Generators, let's recap the basics of asynchronous programming. In JavaScript, asynchronous tasks are crucial for handling time-consuming operations without blocking the main thread. Functions like setTimeout, AJAX requests, and Promises have become commonplace in managing asynchronous operations.</p>
<p>Generators, denoted by <code>function*</code> syntax, are a powerful feature introduced in ES6. They allow us to pause and resume the execution of a function, providing a valuable mechanism for lazy evaluation. The <code>yield</code> keyword within a generator function lets us yield values individually, pausing the function's execution until the next value is requested. If you want to learn more, there is relative content about them in this series.</p>
<p>Now, imagine combining the magic of asynchronous operations with the versatility of generators. Enter Async Generators! These supercharged functions enable us to work with asynchronous data streams more intuitively and elegantly.</p>
<p>An async generator function is declared using <code>async function*</code> syntax. Inside, the <code>yield</code> keyword can be combined with <code>await</code> to handle asynchronous operations gracefully. This means we can yield promises, fetch data and seamlessly integrate it into our data stream.</p>
<p>The real beauty of async generators lies in their ability to simplify complex asynchronous tasks. They're particularly handy when dealing with data streams from sources like databases, APIs, or even real-time event streams. Imagine processing a continuous stream of sensor data or handling multiple concurrent requests without drowning in callback hell!</p>
<p>Let's take a look at an example</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span>* <span class="hljs-title">getUsers</span>(<span class="hljs-params">ids: <span class="hljs-built_in">number</span>[]</span>) </span>{
  <span class="hljs-keyword">for</span> (<span class="hljs-keyword">const</span> id <span class="hljs-keyword">of</span> ids) {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"getUsers next"</span>);
    <span class="hljs-keyword">const</span> data = fetch(<span class="hljs-string">`https://reqres.in/api/users/<span class="hljs-subst">${id}</span>`</span>).then(<span class="hljs-function"><span class="hljs-params">res</span> =&gt;</span>
      res.json()
    );
    <span class="hljs-keyword">yield</span> data;
  }
}
</code></pre>
<p>Using a <code>for-of</code> loop, the function iterates over the IDs and fetches the data for every user on every iteration. However, using the yield, stop the execution and resume it only when the caller asks for the next value.<br />Like Async Iterators, also Async Generators can be iterated using a <code>for-await-of</code> loop.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">for</span> <span class="hljs-keyword">await</span> (<span class="hljs-keyword">const</span> user <span class="hljs-keyword">of</span> getUsers([<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>])) {
  <span class="hljs-built_in">console</span>.log(user);
}
</code></pre>
<p>Error handling and completion are crucial aspects of asynchronous programming. With async generators, we can catch errors using try-catch blocks within the generator function. Plus, we can signal the end of data using the 'return' statement, closing the loop on our data stream.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">try</span> {
  <span class="hljs-keyword">for</span> <span class="hljs-keyword">await</span> (<span class="hljs-keyword">const</span> user <span class="hljs-keyword">of</span> getUsers([<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>])) {
    <span class="hljs-built_in">console</span>.log(user);
  }
} <span class="hljs-keyword">catch</span> (err) {
  <span class="hljs-built_in">console</span>.error(err);
}
</code></pre>
<pre><code class="lang-typescript"><span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span>* <span class="hljs-title">getUsers</span>(<span class="hljs-params">ids: <span class="hljs-built_in">number</span>[]</span>) </span>{
  <span class="hljs-keyword">for</span> (<span class="hljs-keyword">const</span> id <span class="hljs-keyword">of</span> ids) {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"getUsers next"</span>);
    <span class="hljs-keyword">const</span> data = fetch(<span class="hljs-string">`https://reqres.in/api/users/<span class="hljs-subst">${id}</span>`</span>).then(<span class="hljs-function"><span class="hljs-params">res</span> =&gt;</span>
      res.json()
    );
    <span class="hljs-keyword">if</span> (id &gt; <span class="hljs-number">4</span>) <span class="hljs-keyword">return</span> data; <span class="hljs-comment">// &lt;-- Return</span>
    <span class="hljs-keyword">yield</span> data;
  }
}
</code></pre>
<p>Like Generators, also Async Generators can be combined. For instance, we can create an Async Generator <code>map</code> function that accepts an Async Generator and a transformation function and returns a new async generator with the transformations.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span>* <span class="hljs-title">map</span>&lt;<span class="hljs-title">T</span>, <span class="hljs-title">U</span>&gt;(<span class="hljs-params">
  asyncIterable: AsyncIterable&lt;T&gt;,
  callback: (value: T) =&gt; U
</span>) </span>{
  <span class="hljs-keyword">for</span> <span class="hljs-keyword">await</span> (<span class="hljs-keyword">const</span> item <span class="hljs-keyword">of</span> asyncIterable) {
    <span class="hljs-keyword">yield</span> callback(item);
  }
}
</code></pre>
<p>Asynchronous programming in JavaScript continues to evolve, and Async Generators are a testament to its dynamic nature. With their power to elegantly manage complex asynchronous tasks, async generators offer a glimpse into the future of streamlined coding. So, fellow developers, embrace this innovative tool and unlock new possibilities in your projects.</p>
<p>I also created a video about Async Generators on my <a target="_blank" href="https://www.youtube.com/@Puppo_92/">Youtube channel</a> and you can find it below.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://youtu.be/0uQvNZ8th08?si=HxrO1um4xwpydZQu">https://youtu.be/0uQvNZ8th08?si=HxrO1um4xwpydZQu</a></div>
<p> </p>
<p>That's a wrap for today's discussion on JavaScript Async Generators. I hope you found this exploration insightful and inspiring. Remember, staying curious and open to new concepts is the key to mastering your craft in the ever-evolving programming landscape.</p>
<p>If you enjoyed this post, like and share it. And if you have questions, feedback or doubts let me know in the comments.</p>
<p>Until next time, happy coding and thanks for reading 👩‍💻👨‍💻</p>
<p>N.B. you can find the code of this post <a target="_blank" href="https://github.com/Puppo/javascript-iterators-and-generators/tree/04-async-generators">here</a>.</p>
]]></content:encoded></item><item><title><![CDATA[Mastering JavaScript Async Iterators: Unlocking Asynchronous Magic]]></title><description><![CDATA[In the ever-evolving landscape of JavaScript, staying up-to-date with its latest features is crucial for writing efficient and modern code. One such feature that has garnered significant attention is the Async Iterator. While iterators have long been...]]></description><link>https://blog.delpuppo.net/mastering-javascript-async-iterators-unlocking-asynchronous-magic</link><guid isPermaLink="true">https://blog.delpuppo.net/mastering-javascript-async-iterators-unlocking-asynchronous-magic</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[asynchronous]]></category><category><![CDATA[iterator]]></category><category><![CDATA[iterators]]></category><category><![CDATA[js]]></category><dc:creator><![CDATA[Luca Del Puppo]]></dc:creator><pubDate>Fri, 08 Sep 2023 05:16:06 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1693132973722/d00839c4-fdb2-4493-be81-00f724445057.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In the ever-evolving landscape of JavaScript, staying up-to-date with its latest features is crucial for writing efficient and modern code. One such feature that has garnered significant attention is the Async Iterator. While iterators have long been an integral part of JavaScript for sequential data processing, the introduction of asynchronous programming patterns brought about the need for asynchronous iteration.</p>
<p>Imagine effortlessly traversing through data streams that might involve fetching data from APIs, reading from files, or any other asynchronous data source. This is precisely where Async Iterators shine, providing a seamless and elegant solution to handle such scenarios. In this blog post, we'll delve into the world of JavaScript Async Iterators, exploring their fundamentals, understanding their benefits, and uncovering how they can be a game-changer in writing robust asynchronous code. Whether you're a seasoned developer looking to expand your skill set or a newcomer curious about advanced JavaScript techniques, this blog post is for you. We will unravel the power of Async Iterators and take your asynchronous programming skills to new heights.</p>
<p>Before we jump into the code, let's understand what async iterators are. In JavaScript, iterators are objects that allow us to loop over collections. Async iterators take this concept a step further by allowing us to handle asynchronous operations, like fetching data from APIs or reading from streams.</p>
<p>Creating an async iterable is simple. We use the <code>Symbol.asyncIterator</code> to define the async iterator method inside an object. This method will return an object with the <code>next</code> method that resolves a promise containing the <code>next</code> value in the asynchronous sequence.<br />Let's take a look at an example.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">const</span> getUsers = (ids: <span class="hljs-built_in">number</span>[]): AsyncIterable&lt;User&gt; =&gt; {
  <span class="hljs-keyword">return</span> {
    [<span class="hljs-built_in">Symbol</span>.asyncIterator]() {
      <span class="hljs-keyword">let</span> i = <span class="hljs-number">0</span>;
      <span class="hljs-keyword">return</span> {
        <span class="hljs-keyword">async</span> next() {
          <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"getUsers next"</span>);
          <span class="hljs-keyword">if</span> (i === ids.length) {
            <span class="hljs-keyword">return</span> { done: <span class="hljs-literal">true</span>, value: <span class="hljs-literal">null</span> };
          }
          <span class="hljs-keyword">const</span> data = <span class="hljs-keyword">await</span> fetch(
            <span class="hljs-string">`https://reqres.in/api/users/<span class="hljs-subst">${ids[i++]}</span>`</span>
          ).then(<span class="hljs-function"><span class="hljs-params">res</span> =&gt;</span> res.json());
          <span class="hljs-keyword">return</span> { done: <span class="hljs-literal">false</span>, value: data };
        },
      };
    },
  };
};
</code></pre>
<p>Imagine you have a list of IDs and want to read the user data only if needed. Using AsyncIterators, you can create a function that handles the API and returns the result of every request on every iteration, making the code more transparent.</p>
<p>To consume the values of an async iterable, we use the <code>for-await-of</code> loop. This loop works just like the regular <code>for-of</code> loop, but it's designed specifically for asynchronous iterables.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">for</span> <span class="hljs-keyword">await</span> (<span class="hljs-keyword">const</span> user <span class="hljs-keyword">of</span> getUsers([<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>])) {
  <span class="hljs-built_in">console</span>.log(user);
}
</code></pre>
<p>Error handling is crucial when dealing with asynchronous operations. Async iterators allow us to handle errors using <code>try-catch</code> blocks around the <code>for-await-of</code> loop.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">for</span> <span class="hljs-keyword">await</span> (<span class="hljs-keyword">const</span> user <span class="hljs-keyword">of</span> getUsers([<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>])) {
      <span class="hljs-built_in">console</span>.log(user);
    }
  } <span class="hljs-keyword">catch</span> (err) {
    <span class="hljs-built_in">console</span>.error(err);
  }
</code></pre>
<p>AsyncIterator runs code only if needed, so until you don't call the next method, nothing happens, like for Iterators.</p>
<p>The <code>return</code> method exists also for AsyncIterators. This method is used in case the code doesn't complete all the iterations. Imagine the loop calls a break or a return; in this case, JavaScript under the hood calls the <code>return</code> method for us. In this method, we can handle whatever we need. We may need to reset something or check the current value of the iterator.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">const</span> getUsers = (ids: <span class="hljs-built_in">number</span>[]): AsyncIterable&lt;User&gt; =&gt; {
  <span class="hljs-keyword">return</span> {
    [<span class="hljs-built_in">Symbol</span>.asyncIterator]() {
      <span class="hljs-keyword">let</span> i = <span class="hljs-number">0</span>;
      <span class="hljs-keyword">return</span> {
        ...
        <span class="hljs-keyword">async</span> <span class="hljs-keyword">return</span>() {
          <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"getUsers return"</span>);
          <span class="hljs-keyword">return</span> { done: <span class="hljs-literal">true</span>, value: <span class="hljs-literal">null</span> };
        },
      };
    },
  };
};
</code></pre>
<p>Async Iterators are powerful like Iterators, and we can create functions that accept an AsyncIterator and manipulate it to return another Async Iterator. For instance, we can create a map function that accepts an Async Iterator and returns another with a callback specified by the user.</p>
<pre><code class="lang-typescript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">map</span>&lt;<span class="hljs-title">T</span>, <span class="hljs-title">U</span>&gt;(<span class="hljs-params">iter: AsyncIterable&lt;T&gt;, fn: (v: T) =&gt; U</span>): <span class="hljs-title">AsyncIterable</span>&lt;<span class="hljs-title">U</span>&gt; </span>{
  <span class="hljs-keyword">return</span> {
    [<span class="hljs-built_in">Symbol</span>.asyncIterator]() {
      <span class="hljs-keyword">const</span> iterator = iter[<span class="hljs-built_in">Symbol</span>.asyncIterator]();
      <span class="hljs-keyword">return</span> {
        <span class="hljs-keyword">async</span> next() {
          <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"map next"</span>);
          <span class="hljs-keyword">const</span> { done, value } = <span class="hljs-keyword">await</span> iterator.next();
          <span class="hljs-keyword">if</span> (done) <span class="hljs-keyword">return</span> { done, value: <span class="hljs-literal">null</span> };
          <span class="hljs-keyword">return</span> { done, value: fn(value) };
        },
        <span class="hljs-keyword">async</span> <span class="hljs-keyword">return</span>() {
          <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"map return"</span>);
          <span class="hljs-keyword">if</span> (iterator?.return) <span class="hljs-keyword">await</span> iterator?.return();
          <span class="hljs-keyword">return</span> { done: <span class="hljs-literal">true</span>, value: <span class="hljs-literal">null</span> };
        },
      };
    },
  };
}
</code></pre>
<p>These functions have all the benefits said before. Javascript does nothing until the codebase doesn't ask for the next function; the same is true for the <code>return</code> method, and now you can compose the <code>getUsers</code> with the <code>map</code> to build a new Async Iterator.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">const</span> iterator = map(getUsers([<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>]), <span class="hljs-function"><span class="hljs-params">user</span> =&gt;</span> user.data.id)
<span class="hljs-keyword">for</span> <span class="hljs-keyword">await</span> (<span class="hljs-keyword">const</span> num <span class="hljs-keyword">of</span> iterator) {
  <span class="hljs-keyword">if</span> (num === <span class="hljs-number">3</span>) <span class="hljs-keyword">break</span>;
  <span class="hljs-built_in">console</span>.log(num);
}
</code></pre>
<p>And there you have it – a deep dive into the world of asynchronous iterators in JavaScript. They provide an elegant solution to working with asynchronous data streams, making your code more organized and efficient. Experiment with async iterators in your projects, and you'll be amazed at how they simplify complex asynchronous workflows.</p>
<p>I also created a video on my <a target="_blank" href="https://www.youtube.com/@Puppo_92/">Youtube channel</a>, that you can find below.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://www.youtube.com/watch?v=0_mzZ9QOebg">https://www.youtube.com/watch?v=0_mzZ9QOebg</a></div>
<p> </p>
<p>If you found this content helpful, like and share it. And if you have any questions, feedback, or doubts, let me know in the comments 😀</p>
<p>Thanks for reading! And Happy coding! 👩‍💻 👨‍💻</p>
<p>N.B. you can find the code of this post <a target="_blank" href="https://github.com/Puppo/javascript-iterators-and-generators/tree/03-async-iterators">here</a>.</p>
]]></content:encoded></item><item><title><![CDATA[Unleashing the Power: Demystifying JavaScript Generators]]></title><description><![CDATA[Welcome to this blog post, where we're diving into the fascinating world of JavaScript generators. If you're looking to take your coding skills to the next level and explore a powerful tool for managing operations, you've come to the right place.
In ...]]></description><link>https://blog.delpuppo.net/unleashing-the-power-demystifying-javascript-generators</link><guid isPermaLink="true">https://blog.delpuppo.net/unleashing-the-power-demystifying-javascript-generators</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[generators]]></category><category><![CDATA[js]]></category><dc:creator><![CDATA[Luca Del Puppo]]></dc:creator><pubDate>Fri, 01 Sep 2023 04:38:50 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1693132912918/19845e05-d60c-417c-85c2-2f09ab08cb2e.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Welcome to this blog post, where we're diving into the fascinating world of JavaScript generators. If you're looking to take your coding skills to the next level and explore a powerful tool for managing operations, you've come to the right place.</p>
<p>In the fast-paced landscape of web development, managing tasks and handling complex flows of data can be quite challenging. This is where JavaScript generators come into play. These remarkable constructs introduce a new level of control and flexibility, allowing developers to write code that can be paused, resumed, and iterated step by step.</p>
<p>In this blog post, we'll take you on a journey through the core concepts of JavaScript generators. We'll unravel their syntax, explore their capabilities, and showcase examples of how they can simplify your code and make it more manageable. By the end of this read, you'll not only understand the ins and outs of generators but also be equipped with the knowledge to start using them effectively in your own projects.</p>
<p>Buckle up as we embark on this exploration of JavaScript generators, unravelling their potential and discovering how they can revolutionize the way you write code. Whether you're a seasoned developer or just starting with JavaScript, there's something valuable here for you. Let's begin!</p>
<p>A generator in JavaScript is a function that, after the function keyword, has a <code>*</code>. It's not possible to create generators in JavaScript using arrow functions. Generators are special functions that implement the Iterable interface very simply; you can learn more about them in this blog post. The particularity of generators is the <code>yield</code> keyword. Using the <code>yield</code>, we can return a new value to the iteration but without ending the function execution, simply putting it on pause, until the next request for the next value and until it's not completed.</p>
<pre><code class="lang-typescript"><span class="hljs-function"><span class="hljs-keyword">function</span>* <span class="hljs-title">range</span>(<span class="hljs-params">start: <span class="hljs-built_in">number</span>, end: <span class="hljs-built_in">number</span></span>): <span class="hljs-title">Iterable</span>&lt;<span class="hljs-title">number</span>&gt; </span>{
  <span class="hljs-keyword">let</span> n = start;
  <span class="hljs-keyword">while</span> (n &lt;= end) {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"range next"</span>);
    <span class="hljs-keyword">yield</span> n++;
  }
}
</code></pre>
<p>As you can notice, the range generator is a simple generator function, and it's understandable from the <code>*</code> near-function keyword. Using a simple while, the function checks if the current value is less or equal to the end value and if true, using the <code>yield</code> returns the value; else exists from the while and closes the generator. Like iterators, generators only run once someone calls for the <code>next</code> value.</p>
<p>It's possible to go through a generator using a simple for-of-loop.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">for</span> (<span class="hljs-keyword">const</span> num <span class="hljs-keyword">of</span> range(<span class="hljs-number">1</span>, <span class="hljs-number">10</span>)) {
  <span class="hljs-built_in">console</span>.log(num);
}
</code></pre>
<p>Using the Iterable interface</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">const</span> iterator = range(<span class="hljs-number">1</span>, <span class="hljs-number">10</span>)[<span class="hljs-built_in">Symbol</span>.iterator]();
<span class="hljs-keyword">while</span> (<span class="hljs-literal">true</span>) {
  <span class="hljs-keyword">const</span> { done, value } = iterator.next();
  <span class="hljs-keyword">if</span> (done) <span class="hljs-keyword">break</span>;
  <span class="hljs-built_in">console</span>.log(value);
}
</code></pre>
<p>Or using the spread operator to save all the values in an Array.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">for</span> (<span class="hljs-keyword">const</span> num <span class="hljs-keyword">of</span> [...range(<span class="hljs-number">1</span>, <span class="hljs-number">10</span>)]) {
  <span class="hljs-built_in">console</span>.log(num);
}
</code></pre>
<p>It's important to remember that if you use the spread operator, you will lose all the generators' benefits because it runs the generator until it's not completed to copy all the values in the array.</p>
<p>Like iterators also, generators can be combined. For instance, we can create a map generator function that accepts an iterator and a transformation function and returns the computation inside the transformation with the value emitted by the generator.</p>
<p>And that's the result.</p>
<pre><code class="lang-typescript"><span class="hljs-function"><span class="hljs-keyword">function</span>* <span class="hljs-title">map</span>&lt;<span class="hljs-title">T</span>, <span class="hljs-title">U</span>&gt;(<span class="hljs-params">
  iterable: Iterable&lt;T&gt;,
  callback: (value: T) =&gt; U
</span>): <span class="hljs-title">Iterable</span>&lt;<span class="hljs-title">U</span>&gt; </span>{
  <span class="hljs-keyword">for</span> (<span class="hljs-keyword">const</span> value <span class="hljs-keyword">of</span> iterable) {
    <span class="hljs-keyword">yield</span> callback(value);
  }
}

<span class="hljs-keyword">const</span> mapRange = map(range(<span class="hljs-number">1</span>, <span class="hljs-number">10</span>), <span class="hljs-function"><span class="hljs-params">value</span> =&gt;</span> value * <span class="hljs-number">10</span>);

<span class="hljs-keyword">for</span> (<span class="hljs-keyword">const</span> num <span class="hljs-keyword">of</span> mapRange) {
  <span class="hljs-built_in">console</span>.log(num);
}
</code></pre>
<p>That's all folks. You can find a video about them on my <a target="_blank" href="https://www.youtube.com/@Puppo_92/">Youtube channel</a>.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://youtu.be/mi2JlrXBRIs?si=mqP_72pzObZ71QLt">https://youtu.be/mi2JlrXBRIs?si=mqP_72pzObZ71QLt</a></div>
<p> </p>
<p>In conclusion, JavaScript generators stand as a remarkable tool in the arsenal of every developer striving for more efficient and flexible programming. Through their unique ability to pause and resume execution, generators provide an innovative solution to managing complex flows of data and operations.</p>
<p>Throughout this blog post, we've journeyed through the syntax, use cases, and benefits of JavaScript generators. We've seen how they can simplify code, making it more readable and maintainable.</p>
<p>By harnessing the power of generators, you can transform the way you approach programming challenges. These constructs not only offer a structured approach to handling tasks but also contribute to writing code that is less error-prone and easier to reason about.</p>
<p>As you venture into the realm of generators, remember that practice is key. Experiment with different scenarios, explore their interplay with other techniques and gradually integrate them into your projects. With time, you'll become proficient in leveraging generators to create responsive and efficient applications.</p>
<p>So, whether you're a front-end developer aiming to tame complex UI interactions or a back-end engineer dealing with intricate data processing, generators offer a fresh perspective on tackling programming. Embrace their power, refine your skills, and elevate your coding prowess in the dynamic world of JavaScript.</p>
<p>Thank you for reading and happy generating! 👩‍💻 👨‍💻 😜</p>
<p>N.B. you can find the code of this post <a target="_blank" href="https://github.com/Puppo/javascript-iterators-and-generators/tree/02-generators">here</a>.</p>
]]></content:encoded></item><item><title><![CDATA[Iterate Like a Pro: Mastering JavaScript Iterators for Effortless Code]]></title><description><![CDATA[Welcome to this blog post, where we're about to unravel the power and versatility of JavaScript iterators. If you've ever found yourself working with data collections and wondered if there's a more efficient and elegant way to navigate them, you're i...]]></description><link>https://blog.delpuppo.net/iterate-like-a-pro-mastering-javascript-iterators-for-effortless-code</link><guid isPermaLink="true">https://blog.delpuppo.net/iterate-like-a-pro-mastering-javascript-iterators-for-effortless-code</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[iterator]]></category><category><![CDATA[js]]></category><category><![CDATA[iterators]]></category><dc:creator><![CDATA[Luca Del Puppo]]></dc:creator><pubDate>Fri, 25 Aug 2023 06:10:55 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1692600372219/e008b05a-5b8d-4f83-a935-a1f831bb6e6f.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Welcome to this blog post, where we're about to unravel the power and versatility of JavaScript iterators. If you've ever found yourself working with data collections and wondered if there's a more efficient and elegant way to navigate them, you're in the right place.</p>
<p>In the realm of modern web development, efficiently managing and manipulating data is a crucial skill. This is where JavaScript iterators come into play, offering a systematic approach to traversing various data structures such as arrays, maps, and sets. Whether you're a beginner eager to understand the basics or an experienced developer looking to fine-tune your code, grasping the concept of iterators can significantly enhance your programming journey.</p>
<p>In this blog post, we'll embark on a comprehensive exploration of JavaScript iterators. We'll break down their fundamental principles, explore practical examples of their usage, and demonstrate how they can simplify complex data operations. By the time you finish reading, you'll not only understand iterators inside and out but also be equipped to leverage their potential to write more concise, readable, and efficient code.</p>
<p>So, whether you're striving to make your codebase more elegant or seeking to optimize your data manipulation techniques, join us as we delve into the world of JavaScript iterators. From novice to expert, there's something here for everyone. Let's dive in!</p>
<p>Built-in in Javascript exists many structures that implement the Iterators pattern, for instance: Array, Set and Map. In Javascript, an object to be iterable must implement the Iterable interface.</p>
<p>But what is the Iterable interface? First, to be iterable, an object must have a <code>next</code> method. This method must return two properties: <code>done</code> and <code>value</code>. Done is used to detect if the iteration is completed; instead, the value contains the current value. Last but not least, if you want your object to become an iterator, you must expose the iterable interface in the <code>Symbol.iterator</code> of your object, like in this example.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">const</span> array = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>];
<span class="hljs-keyword">const</span> iterator = array[<span class="hljs-built_in">Symbol</span>.iterator]();
<span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> result = iterator.next(); !result.done; result = iterator.next()) {
  <span class="hljs-built_in">console</span>.log(result.value);
}
</code></pre>
<p>For example, here is a range function implemented as an iterator.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">const</span> range = (start: <span class="hljs-built_in">number</span>, end: <span class="hljs-built_in">number</span>): Iterable&lt;<span class="hljs-built_in">number</span>&gt; =&gt; {
  <span class="hljs-keyword">return</span> {
    [<span class="hljs-built_in">Symbol</span>.iterator]() {
      <span class="hljs-keyword">let</span> n = start;
      <span class="hljs-keyword">return</span> {
        next() {
          <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"range next"</span>);
          <span class="hljs-keyword">if</span> (n &gt; end) {
            <span class="hljs-keyword">return</span> { done: <span class="hljs-literal">true</span>, value: <span class="hljs-literal">null</span> };
          }
          <span class="hljs-keyword">return</span> { done: <span class="hljs-literal">false</span>, value: n++ };
        },
      };
    },
  };
};
</code></pre>
<p>As you can notice, this function accepts two numbers, start and end and returns a new object with a single property, in this case, the iterator property. Then, inside this function, there is the next function that, on every call, checks if the current value is greater than the end and, if true, returns a new object with done as true and value as null; else returns an object with done false and value with the current value. The beautiful thing about iterator is that javascript only does something once you ask for the next value.</p>
<p>Every iterator can be iterated using the for-of loop</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">for</span> (<span class="hljs-keyword">const</span> num <span class="hljs-keyword">of</span> range(<span class="hljs-number">1</span>, <span class="hljs-number">10</span>)) {
  <span class="hljs-built_in">console</span>.log(num);
}
</code></pre>
<p>or using its native method, so calling the <code>Symbol.iterator</code> function and then using the next method and checking the done property if it is true or not.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">const</span> rangeIterator = range(<span class="hljs-number">1</span>, <span class="hljs-number">10</span>)[<span class="hljs-built_in">Symbol</span>.iterator]();
<span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> result = rangeIterator.next(); !result.done; result = rangeIterator.next()) {
  <span class="hljs-built_in">console</span>.log(result.value);
}
</code></pre>
<p>It's possible to copy all the iterator values in an Array using the spread operator too.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">for</span> (<span class="hljs-keyword">const</span> num <span class="hljs-keyword">of</span> [...range(<span class="hljs-number">1</span>, <span class="hljs-number">10</span>)]) {
  <span class="hljs-built_in">console</span>.log(num);
}
</code></pre>
<p>Iterator also has another method, the <code>return</code> method. This method is used in case the code doesn't complete the iteration. Imagine the loop call a break or a return; in this case, JavaScript under the hood calls the <code>return</code> method for us. In this method, we can handle whatever we need. We may need to reset something or check the current value of the iterator.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">const</span> range = (start: <span class="hljs-built_in">number</span>, end: <span class="hljs-built_in">number</span>): Iterable&lt;<span class="hljs-built_in">number</span>&gt; =&gt; {
  <span class="hljs-keyword">return</span> {
    [<span class="hljs-built_in">Symbol</span>.iterator]() {
      <span class="hljs-keyword">let</span> n = start;
      <span class="hljs-keyword">return</span> {
        next() {
          <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"range next"</span>);
          <span class="hljs-keyword">if</span> (n &gt; end) {
            <span class="hljs-keyword">return</span> { done: <span class="hljs-literal">true</span>, value: <span class="hljs-literal">null</span> };
          }
          <span class="hljs-keyword">return</span> { done: <span class="hljs-literal">false</span>, value: n++ };
        },
        <span class="hljs-keyword">return</span>() {
          <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"range return"</span>);
          <span class="hljs-keyword">return</span> { done: <span class="hljs-literal">true</span>, value: <span class="hljs-literal">null</span> };
        },
      };
    },
  };
};

<span class="hljs-keyword">for</span> (<span class="hljs-keyword">const</span> num <span class="hljs-keyword">of</span> range(<span class="hljs-number">1</span>, <span class="hljs-number">10</span>)) {
  <span class="hljs-keyword">if</span> (num &gt; <span class="hljs-number">5</span>) <span class="hljs-keyword">break</span>;
  <span class="hljs-built_in">console</span>.log(num);
}
</code></pre>
<p>Iterators are powerful, and we can also create functions that accept an iterator and manipulate it to return another iterator. For instance, we can create a map function that accepts an iterator and returns another with a callback specified by the user.</p>
<pre><code class="lang-typescript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">mapIterable</span>&lt;<span class="hljs-title">T</span>, <span class="hljs-title">U</span>&gt;(<span class="hljs-params">
  iterable: Iterable&lt;T&gt;,
  callback: (value: T) =&gt; U
</span>): <span class="hljs-title">Iterable</span>&lt;<span class="hljs-title">U</span>&gt; </span>{
  <span class="hljs-keyword">return</span> {
    [<span class="hljs-built_in">Symbol</span>.iterator]() {
      <span class="hljs-keyword">const</span> iterator = iterable[<span class="hljs-built_in">Symbol</span>.iterator]();
      <span class="hljs-keyword">return</span> {
        next() {
          <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"mapIterable next"</span>);
          <span class="hljs-keyword">const</span> { done, value } = iterator.next();
          <span class="hljs-keyword">if</span> (done) {
            <span class="hljs-keyword">return</span> { done: <span class="hljs-literal">true</span>, value: <span class="hljs-literal">null</span> };
          }
          <span class="hljs-keyword">return</span> { done, value: callback(value) };
        },
        <span class="hljs-keyword">return</span>() {
          <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"mapIterable return"</span>);
          <span class="hljs-keyword">if</span> (iterator.return) {
            iterator.return();
          }
          <span class="hljs-keyword">return</span> { done: <span class="hljs-literal">true</span>, value: <span class="hljs-literal">null</span> };
        },
      };
    },
  };
}
</code></pre>
<p>All the info said before is true also for this new iterator. JavaScript does nothing until the codebase doesn't ask for the next value; the same is true for the return method, and now you can compose the range iterators with the map iterator to build a new one.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">const</span> mapRange = mapIterable(range(<span class="hljs-number">1</span>, <span class="hljs-number">10</span>), <span class="hljs-function"><span class="hljs-params">value</span> =&gt;</span> value * <span class="hljs-number">10</span>);

<span class="hljs-keyword">for</span> (<span class="hljs-keyword">const</span> num <span class="hljs-keyword">of</span> mapRange) {
  <span class="hljs-keyword">if</span> (num &gt; <span class="hljs-number">50</span>) <span class="hljs-keyword">break</span>;
  <span class="hljs-built_in">console</span>.log(num);
}
</code></pre>
<p>Ok folks, that's all!<br />If you want to dive deep with Iterators, don't waste my video on my <a target="_blank" href="https://www.youtube.com/@Puppo_92/">Youtube channel</a>.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://www.youtube.com/watch?v=BSctSkMGtiM">https://www.youtube.com/watch?v=BSctSkMGtiM</a></div>
<p> </p>
<p>In conclusion, understanding and utilizing JavaScript iterators can greatly enhance your ability to work with collections of data in a more elegant and efficient manner. With iterators, you can streamline your code, improve its readability, and reduce memory consumption by processing data one element at a time. This powerful concept empowers developers to implement custom iteration behaviour, making their code more adaptable to different scenarios.</p>
<p>By grasping the fundamentals of iterators, such as the <code>next()</code> method and the concept of iterable objects, you open the door to more sophisticated programming techniques and design patterns. Whether you're working with arrays, maps, sets, or other data structures, iterators provide a standardized way to traverse through data and perform operations without unnecessary complexity.</p>
<p>As the JavaScript language continues to evolve, iterators remain a foundational concept that plays a crucial role in modern programming paradigms. Incorporating iterators into your coding arsenal equips you with a versatile tool for managing data, ultimately leading to cleaner, more maintainable, and more robust code.</p>
<p>So, as you embark on your journey to master JavaScript iterators, remember that they are more than just technical features; they represent a shift in how you approach and solve problems in your code. With practice and exploration, you'll be able to wield iterators effectively, making your codebase more efficient and your development experience more enjoyable.</p>
<p>Thanks for reading and Happy coding! 😃 👩‍💻 👨‍💻</p>
<p>N.B. you can find the code of this article <a target="_blank" href="https://github.com/Puppo/javascript-iterators-and-generators/tree/01-iterators">here</a>!</p>
]]></content:encoded></item><item><title><![CDATA[🏆 My journey to the MVP Award 🏆]]></title><description><![CDATA[This history started many years ago! I was a student, and I was going to the ITS in Pordenone.I spent two years of my life in that school, where I met great friends and learned a lot from awesome teachers, one of them is Andrea Dottor.In the first le...]]></description><link>https://blog.delpuppo.net/my-journey-to-the-mvp-award</link><guid isPermaLink="true">https://blog.delpuppo.net/my-journey-to-the-mvp-award</guid><category><![CDATA[Awards]]></category><category><![CDATA[Microsoft]]></category><category><![CDATA[journey]]></category><category><![CDATA[mvp]]></category><dc:creator><![CDATA[Luca Del Puppo]]></dc:creator><pubDate>Fri, 09 Jun 2023 05:30:39 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/d1eaoAabeXs/upload/ecf36218be28db2b0f3bcf3922604b4d.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>This history started many years ago! I was a student, and I was going to the <a target="_blank" href="https://www.itsaltoadriatico.it/">ITS</a> in Pordenone.<br />I spent two years of my life in that school, where I met great friends and learned a lot from awesome teachers, one of them is <a target="_blank" href="https://www.dottor.net/">Andrea Dottor</a>.<br />In the first lesson with him, he started with his presentation, "I'm a freelancer, I work with different companies and blah blah blah... I'm a Microsoft MVP too".<br />That was the first time that I heard about this program. As you can imagine, I was 20, and I didn't get any importance to that tense, but in reality, it was the first moment that I came across the MVP program.</p>
<p>After that, Andrea and I became colleagues and friends. I always see Andrea as a Mentor, and I have always followed him. So I started to go with him to the <a target="_blank" href="https://www.xedotnet.org/">xedotnet</a> meetup. I met other incredible developers like <a target="_blank" href="https://mvp.microsoft.com/en-us/PublicProfile/4039714?fullName=Mirco%20Vanini">Mirco Vanini</a> (another MVP), Daniele Morosinotto and many others there. Thanks to xe, I learned what a community is and how a community works. I started to understand the benefit of sharing knowledge in the development environment, and my mind started to build a strange idea "One day you will be like them, maybe not an MVP but a speaker yes, and you will share your knowledge with the others."</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1682441754145/597ab828-4c01-48b9-96fb-ec31b8ec82fb.jpeg" alt="Andrea and I during a running by night" class="image--center mx-auto" /></p>
<p>I was young at that moment and decided to continue to follow the community, but I put my effort into improving myself in my job.<br />For almost 8 years, I dedicated my time to learn stuff in my bedroom and in my free time, developing different projects in my daily routine, and I changed 3 jobs too.<br />When I started to work in Flowing, in my mind something happened.<br />Flowing was an environment with awesome developers, and many of them were and are speakers too. But I was not ready to do my first talk, so I tried to think of something different that could be useful for the community. After some days, I decided to write my first series about Typescripts.<br />Why typescript? It is my favorite language with javascript, and many times, I saw people fighting with it. So I said: "Ok, this is the right topic, let's go!".<br />21 articles compose my first series, "<strong>Typescript - Tips &amp; Tricks Series</strong>", which you can find <a target="_blank" href="https://dev.to/puppo/series/11213">here</a>. In reality, the audience at the beginning was not so much, but after some months, <a target="_blank" href="https://twitter.com/LayZeeDK">Lars</a> contacted me to ask if I would join the "<a target="_blank" href="https://dev.to/this-is-learning">This is learning</a>" community, and as you can imagine, I accepted :) Here I also met another good man: <a target="_blank" href="https://twitter.com/SantoshYadavDev">Santosh</a>, who runs with Lars "This is learning" community.<br />During that period, another crazy and good friend had a strange idea. I organized and took as "Teacher" a workshop about Nx in Flowing, and he was invited as an attendee. He appreciated the workshop so much that he invited me to his youtube channel to speak about Nx (<a target="_blank" href="https://www.youtube.com/watch?v=hS_2Okd-CkM">Nx the return</a>). The name of the friend is <a target="_blank" href="https://mvp.microsoft.com/en-us/PublicProfile/5003974?fullName=Francesco%20Sciuti">Francesco Sciuti</a>, another MVP and also the Batman of the developers.<br />In that period, I was also writing a new series called "<a target="_blank" href="https://dev.to/puppo/series/13743">RxJS - Getting Started</a>", 15 articles to help developers to be more confident with <a target="_blank" href="https://rxjs.dev/">RxJS</a>. Why this topic? Because I worked on many Angular projects and saw many developers stuck or completely unfamiliar with it.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1682441809835/0f5ef1a1-13b9-4368-8da1-288453d3b001.jpeg" alt="Francesco and I at GDP Pescara" class="image--center mx-auto" /></p>
<p>After that, a colleague and friend (<a target="_blank" href="https://www.linkedin.com/in/francescostrazzullo/">Francesco Strazzullo</a>) tried to push me out of my comfort zone, and he asked me to be a speaker at the <a target="_blank" href="https://marcausergroup.it/">Mug</a> meetup. I was a bit scared; speaking in front of many people created a strange sensation in me, but after some sane pushing, I said yes! So the 7th of October 2021, I did my first talk called <a target="_blank" href="https://marcausergroup.it/eventi/2021/10/07/stay-reactive-stay-quiet-with-rxjs.html">Stay Reactive Stay Quiet with RxJS</a>. The sensations at the end were really good, so on the 19th of October, I did the second at the <a target="_blank" href="https://www.fevr.it/">FEVR</a> community called "<a target="_blank" href="https://www.fevr.it/eventi/2021/10/is-it-possible-to-build-your-ui-components-using-only-web-components/">Is it possible to build your UI components using only web components?</a>" (thanks to <a target="_blank" href="https://www.linkedin.com/in/matteoguidotto/">Matteo Guidotto</a> for this talk).<br />It was the COVID period, so taking talks and doing conferences in 2021 was really difficult. For this reason, I continued to write another series called: <a target="_blank" href="https://dev.to/puppo/series/15827">It's Prisma Time</a>.</p>
<p>At the beginning of 2022, the decisive turning point. During a chat with Andrea, I told him: "I would become a Microsoft MVP; what have I to do to achieve it?" I had this idea for some months, but I wanted to concretize it at that moment. He looked at me and said, "It's time to do some great conferences and maybe speak more about some Microsoft technologies".<br />So I went back home, and with the euphoria in my blood, I started to write some articles about <a target="_blank" href="https://dev.to/puppo/series/16773">Visual Studio Code</a>. These articles spoke about some common commands for me when I worked with VsCode, but these articles were awesome for the community! Many and many people didn't know these commands, and the articles received a lot of appreciation. Another thing I did was research conferences and check out conferences where I could send a CFP.<br />I remember I sent so many CFPs that I forgot how many noes I received 😅<br />But at the beginning of September, the first confirmations arrived: <a target="_blank" href="https://2022.angularday.it/talks_speakers/">AngularDay 2022</a>, then the <a target="_blank" href="https://2022.reactjsday.it/workshop/workshop_Unit-Test.html">workshop</a> at the react day with <a target="_blank" href="https://mvp.microsoft.com/en-us/PublicProfile/5003526?fullName=Fabio%20Biondi">Fabio Biondi</a>, another MVP and good friend that shared with me also a great weekend at the GDP Pescara, where I talked about <a target="_blank" href="https://devfest.gdgpescara.it/sessions/304">Prisma</a> and last but not least the <a target="_blank" href="https://www.youtube.com/watch?v=h_Faplx37yk">ngrome</a>.<br />During this period, I also continued to do meetups, thanks to <a target="_blank" href="https://www.meetup.com/it-IT/milano-front-end/">Milano Frontend</a> and <a target="_blank" href="https://www.meetup.com/it-IT/react-js-milano/">React JS Milano</a> having me as a speaker.<br />If you are curious, you can find the list of all my talks and contributions <a target="_blank" href="https://mvp.microsoft.com/en-us/PublicProfile/5005133?fullName=Luca%20Del%20Puppo">here</a>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1682441933231/b8126fb5-db35-437d-abe6-83ba82da18e4.jpeg" alt="GDP Pescare with friends" class="image--center mx-auto" /></p>
<p>In the middle of December 2022, I spoke again with Andrea to ask him if he could nominate me as Microsoft MVP. He did it, and I spent an evening filling out the form of all my contributions during the last year. Why last year? Because the MVP Award is based on the last year. I started my history 10 years ago, yes, but the MVP Award takes into consideration only the last year. I decided to tell you the entire story because I know the last year is only the cherry on top, but without the previous nine, the last year would probably be a failure.</p>
<p>As you can imagine, after the filling, you have to wait for the evaluation, which takes at most 3 months. I was lucky; on the 3rd of January 2023, in my inbox appeared an email that said: "Congratulation! You are a Microsoft MVP 2023"! Now, I suppose you can imagine how much happy I was, I think I stayed euphory for the following two or three days 😅<br />Then after some weeks, I did a call with <a target="_blank" href="https://www.linkedin.com/in/crisgonz/">Cristina</a>. She takes care of all the MVPs on the Meditterian side and explained to me how the program works, its benefits and so on. She is really kind and she really put a lot of effort into helping the MVPs. Thanks Cristina, for all the things you do for us! 🫶</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1682442061423/c0122998-9147-45fe-b802-ae312657339f.jpeg" alt="Juri and I at angularday IT" class="image--center mx-auto" /></p>
<p>Now my journey is only at the beginning. I have different ideas for continuing.<br />I opened my own <a target="_blank" href="https://www.youtube.com/@Puppo_92">Youtube channel,</a> I'll continue to write articles, and I'll continue to do talks at conferences and meetups.</p>
<p><strong>What did I learn from this story?</strong><br />The MVP award is "only" a simple and beautiful award that helps me remember all the effort I put in these years to improve myself and try to help others! And if you want to join the program: love communities, and put your effort into helping them! Do this, and you'll be on the right path to being part of the MVP Family.<br />Remember: <strong>improve yourself, help others and follow your passion!</strong></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1682165702062/bd016870-0d47-4e22-a171-b2c78fddbb9a.jpeg" alt class="image--center mx-auto" /></p>
]]></content:encoded></item><item><title><![CDATA[React Query - Infinite Queries]]></title><description><![CDATA[Hey Folks,
Today it's time to learn how you can build an infinite query with React Query.
To build an infinite query you have to use the useInfiniteQuery hook. This hook is similar to the useQuery but with some more properties to handle the infinite ...]]></description><link>https://blog.delpuppo.net/react-query-infinite-queries</link><guid isPermaLink="true">https://blog.delpuppo.net/react-query-infinite-queries</guid><category><![CDATA[React]]></category><category><![CDATA[ReactHooks]]></category><category><![CDATA[reactquery]]></category><dc:creator><![CDATA[Luca Del Puppo]]></dc:creator><pubDate>Wed, 07 Jun 2023 05:30:39 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/o4SzxPgMwV8/upload/c11ec8a06625444d23f47684fe0a8870.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Hey Folks,</p>
<p>Today it's time to learn how you can build an infinite query with React Query.</p>
<p>To build an infinite query you have to use the <code>useInfiniteQuery</code> hook. This hook is similar to the <code>useQuery</code> but with some more properties to handle the infinite loading in the best way.</p>
<p>The key concepts, if you are working with <code>useInfiniteQuery</code> are:</p>
<ul>
<li><p><strong>Key</strong>: in this case, the key is unique for each page, <code>useInfiniteQuery</code> handles all the pages inside its state</p>
</li>
<li><p><strong>page</strong>: each chunk of your infinite query is represented as a page and the first page returned by the <code>useInfiniteQuery</code> is undefined. This helps you to understand if it's the first iteration or not.</p>
</li>
<li><p><strong>hasNextPage</strong>: is a variable returned by the hook and its scope is to determine if another chunk exists or not</p>
</li>
<li><p><strong>fetchNextPage</strong>: is a function used to fetch the next chunk</p>
</li>
<li><p><strong>isLoading</strong>: is a flag that determines if there is a loading ongoing (The query has no data yet)</p>
</li>
<li><p><strong>isFetching</strong>: is a flag that determines if there is a fetch request ongoing</p>
</li>
<li><p><strong>getNextPageParam</strong>: this function is an option to pass at the hook and it is used to determine if there is another chunk or not after the response</p>
</li>
</ul>
<p>ok, let's see the code to be clearer</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { useInfiniteQuery } <span class="hljs-keyword">from</span> <span class="hljs-string">'@tanstack/react-query'</span>;
<span class="hljs-keyword">import</span> { useState } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

<span class="hljs-keyword">const</span> fetchTodos = <span class="hljs-keyword">async</span> (
  page: <span class="hljs-built_in">number</span>,
  limit: <span class="hljs-built_in">number</span>,
  signal: AbortSignal | <span class="hljs-literal">undefined</span>
): <span class="hljs-built_in">Promise</span>&lt;{
  totals: <span class="hljs-built_in">number</span>;
  todos: Todo[];
}&gt; =&gt; {
  <span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> fetch(<span class="hljs-string">`api/tasks?_page=<span class="hljs-subst">${page + <span class="hljs-number">1</span>}</span>&amp;_limit=<span class="hljs-subst">${limit}</span>`</span>, {
    signal,
  });
  <span class="hljs-keyword">if</span> (!response.ok) {
    <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> ResponseError(<span class="hljs-string">'Failed to fetch todos'</span>, response);
  }
  <span class="hljs-keyword">const</span> todos: Todo[] = <span class="hljs-keyword">await</span> response.json();
  <span class="hljs-keyword">const</span> totals = <span class="hljs-built_in">Number</span>.parseInt(
    response.headers.get(<span class="hljs-string">'x-total-count'</span>) || <span class="hljs-string">'0'</span>,
    <span class="hljs-number">10</span>
  );

  <span class="hljs-keyword">return</span> {
    totals,
    todos,
  };
};

<span class="hljs-keyword">interface</span> UseTodos {
  todos: Todo[];
  isLoading: <span class="hljs-built_in">boolean</span>;
  isFetching: <span class="hljs-built_in">boolean</span>;
  error?: <span class="hljs-built_in">string</span>;
  hasNext: <span class="hljs-built_in">boolean</span>;
  next?: <span class="hljs-function">() =&gt;</span> <span class="hljs-built_in">void</span>;
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> useTodos = (): <span class="hljs-function"><span class="hljs-params">UseTodos</span> =&gt;</span> {
  <span class="hljs-keyword">const</span> [limit] = useState&lt;<span class="hljs-built_in">number</span>&gt;(<span class="hljs-number">5</span>);

  <span class="hljs-keyword">const</span> { data, hasNextPage, fetchNextPage, isLoading, isFetching, error } =
    useInfiniteQuery(
      [QUERY_KEY.todos],
      <span class="hljs-function">(<span class="hljs-params">{ signal, pageParam: page = <span class="hljs-number">0</span> }</span>) =&gt;</span> fetchTodos(page, limit, signal),
      {
        refetchOnWindowFocus: <span class="hljs-literal">false</span>,
        retry: <span class="hljs-number">2</span>,
        getNextPageParam: <span class="hljs-function">(<span class="hljs-params">lastPage, pages</span>) =&gt;</span> {
          <span class="hljs-keyword">if</span> (<span class="hljs-built_in">Math</span>.ceil(lastPage.totals / limit) &gt; pages.length)
            <span class="hljs-keyword">return</span> pages.length;
          <span class="hljs-keyword">return</span> <span class="hljs-literal">undefined</span>;
        },
      }
    );

  <span class="hljs-keyword">return</span> {
    todos: data?.pages.flatMap(<span class="hljs-function">(<span class="hljs-params">{ todos }</span>) =&gt;</span> todos) || [],
    isLoading,
    isFetching,
    error: mapError(error),
    next: fetchNextPage,
    hasNext: hasNextPage || <span class="hljs-literal">false</span>,
  };
};
</code></pre>
<p>As you can notice, the flow is very simple, the hook returns the current page or chunk, you have to handle the fetch request and then you can determine the result and if there is another chunk or not.<br />Another important thing to keep in mind is that the result of the <code>useInfiniteQuery</code> is an array and each element of the array contains the data of each chunk.</p>
<p>Ok, I suppose you have an idea of how Infinite Queries work in React Query, but if you want to deep into it don't miss my youtube about it.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://www.youtube.com/watch?v=F1KD4GY1iws">https://www.youtube.com/watch?v=F1KD4GY1iws</a></div>
<p> </p>
<p>I think that’s all from this article.</p>
<p>This is the last post of this series, I hope you enjoyed the content and now you are aware of using ReactQuery in your React application.</p>
<p>See you soon folks<br />Bye Bye 👋</p>
<p>p.s. you can find the code of the video <a target="_blank" href="https://github.com/Puppo/learning-react-query/tree/12-infinitive-scroll"><strong>here</strong></a></p>
]]></content:encoded></item><item><title><![CDATA[React Query - Paginated List]]></title><description><![CDATA[Hey Folks,
Today it's time to learn how you can paginate a list with ReactQuery.
It's common to create a pagination of a list to improve the user interface of your platform if you are building a list in your application, but also to limitate the work...]]></description><link>https://blog.delpuppo.net/react-query-paginated-list</link><guid isPermaLink="true">https://blog.delpuppo.net/react-query-paginated-list</guid><category><![CDATA[React]]></category><category><![CDATA[ReactHooks]]></category><category><![CDATA[reactquery]]></category><dc:creator><![CDATA[Luca Del Puppo]]></dc:creator><pubDate>Thu, 01 Jun 2023 06:14:11 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/o4SzxPgMwV8/upload/c11ec8a06625444d23f47684fe0a8870.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Hey Folks,</p>
<p>Today it's time to learn how you can paginate a list with ReactQuery.</p>
<p>It's common to create a pagination of a list to improve the user interface of your platform if you are building a list in your application, but also to limitate the work in your API.</p>
<p>Using ReactQuery, building a paginate list is a piece of cake.</p>
<p>You have to follow 3 steps:</p>
<ol>
<li><p>Create a state to save the value of the current page</p>
</li>
<li><p>Create a state to save the limit of the pages (the number of elements on every page)</p>
</li>
<li><p>Fetch the data every time the user changes one of the previous states.</p>
</li>
</ol>
<p>But let's see an example that is easier to understand</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">const</span> fetchTodos = <span class="hljs-keyword">async</span> (
  page: <span class="hljs-built_in">number</span>,
  limit: <span class="hljs-built_in">number</span>,
  signal: AbortSignal | <span class="hljs-literal">undefined</span>
): <span class="hljs-built_in">Promise</span>&lt;{
  totals: <span class="hljs-built_in">number</span>;
  todos: Todo[];
}&gt; =&gt; {
  <span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> fetch(<span class="hljs-string">`api/tasks?_page=<span class="hljs-subst">${page}</span>&amp;_limit=<span class="hljs-subst">${limit}</span>`</span>, {
    signal,
  });
  <span class="hljs-keyword">if</span> (!response.ok) {
    <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> ResponseError(<span class="hljs-string">'Failed to fetch todos'</span>, response);
  }
  <span class="hljs-keyword">const</span> todos: Todo[] = <span class="hljs-keyword">await</span> response.json();
  <span class="hljs-keyword">const</span> totals = <span class="hljs-built_in">Number</span>.parseInt(
    response.headers.get(<span class="hljs-string">'x-total-count'</span>) || <span class="hljs-string">'0'</span>,
    <span class="hljs-number">10</span>
  );

  <span class="hljs-keyword">return</span> {
    totals,
    todos,
  };
};

<span class="hljs-keyword">interface</span> UseTodos {
  todos: Todo[];
  isLoading: <span class="hljs-built_in">boolean</span>;
  isFetching: <span class="hljs-built_in">boolean</span>;
  error?: <span class="hljs-built_in">string</span>;
  pages: <span class="hljs-built_in">number</span>;
  page: <span class="hljs-built_in">number</span>;
  setPage: Dispatch&lt;SetStateAction&lt;<span class="hljs-built_in">number</span>&gt;&gt;;
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> useTodos = (): <span class="hljs-function"><span class="hljs-params">UseTodos</span> =&gt;</span> {
  <span class="hljs-keyword">const</span> [page, setPage] = useState&lt;<span class="hljs-built_in">number</span>&gt;(<span class="hljs-number">1</span>);
  <span class="hljs-keyword">const</span> [limit] = useState&lt;<span class="hljs-built_in">number</span>&gt;(<span class="hljs-number">5</span>);

  <span class="hljs-keyword">const</span> {
    data: { todos, totals } = {
      todos: [],
      totals: <span class="hljs-number">0</span>,
    },
    isLoading,
    isFetching,
    error,
  } = useQuery(
    [QUERY_KEY.todos, page, limit],
    <span class="hljs-function">(<span class="hljs-params">{ signal }</span>) =&gt;</span> fetchTodos(page, limit, signal),
    {
      refetchOnWindowFocus: <span class="hljs-literal">false</span>,
      retry: <span class="hljs-number">2</span>,
    }
  );

  <span class="hljs-keyword">return</span> {
    todos,
    isLoading,
    isFetching,
    error: mapError(error),
    pages: <span class="hljs-built_in">Math</span>.ceil(totals / limit),
    page,
    setPage,
  };
};
</code></pre>
<p>As you can notice, the process to build a pagination with ReactQuery is very simple.<br />The fetch request has to contain the page and the limit (you can handle a pagination also with limit and offset if you want) and in your <code>useQuery</code> you have to handle some simple stuff. First, the key of your query must include the page and limit too, second you must pass page and limit to your fetch request.</p>
<p>As you can see, building a paginated list with ReactQuery is really a piece of cake, but if want to dive into it don't miss my youtube video about it</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://www.youtube.com/watch?v=Ma7-hdNMdWs">https://www.youtube.com/watch?v=Ma7-hdNMdWs</a></div>
<p> </p>
<p>I think that’s all from this article; I hope you enjoyed this content!</p>
<p>See you soon folks<br />Bye Bye 👋</p>
<p>p.s. you can find the code of the video <a target="_blank" href="https://github.com/Puppo/learning-react-query/tree/11-paginate-result"><strong>here</strong></a></p>
]]></content:encoded></item></channel></rss>