<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Arunish</title>
    <description>The latest articles on Forem by Arunish (@arunish).</description>
    <link>https://forem.com/arunish</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3596747%2F10f7dd6e-2031-4166-9104-9c46fb2beaec.png</url>
      <title>Forem: Arunish</title>
      <link>https://forem.com/arunish</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/arunish"/>
    <language>en</language>
    <item>
      <title>Introducing Apiction: Talk To Any AI Model From Any Provider</title>
      <dc:creator>Arunish</dc:creator>
      <pubDate>Tue, 24 Mar 2026 11:35:21 +0000</pubDate>
      <link>https://forem.com/arunish/introducing-apiction-32mj</link>
      <guid>https://forem.com/arunish/introducing-apiction-32mj</guid>
      <description>&lt;p&gt;AI tooling has exploded. There are chat interfaces, API playgrounds, model routers, and local runners. Most of which do one thing well and nothing else. &lt;/p&gt;

&lt;p&gt;If you want to compare different AI models or different AI model providers, test the same prompt across five providers, switch between image generation and text in the same session, or give a model access to real-time web search, you'd be juggling across three or four different apps to do it.&lt;/p&gt;

&lt;p&gt;I created Apiction to fix that. It is a browser-based, model- and provider-agnostic AI workspace. &lt;/p&gt;

&lt;p&gt;You bring your own API keys, and it handles the rest. Conversations, tools, images, summaries, debugging for developers, and more. Everything is stored in your browser and you can run it locally.&lt;/p&gt;

&lt;p&gt;This article walks through what you can do with it, both as a general user and as a developer.&lt;/p&gt;




&lt;h2&gt;
  
  
  For Everyone
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. General Text Conversations
&lt;/h3&gt;

&lt;p&gt;The most obvious use is chatting with AI models. You type a message, get a response, continue the conversation. Nothing groundbreaking there.&lt;/p&gt;

&lt;p&gt;What is a bit different is you can run conversations in separate tabs with their own separate settings and memory handling. More on that in a bit. &lt;/p&gt;

&lt;p&gt;Apiction renders Markdown responses properly. It renders Math equations via KaTeX, code blocks with syntax highlighting, so you can have nicely formatted responses without needing to open them in another app. Just make sure to set the system prompt to ask the model to respond in Markdown format, and it will do the rest.&lt;/p&gt;

&lt;p&gt;Streaming is supported. So responses appear word by word as they generate, however the rendering during stream is kept lightweight and the full Markdown render only happens when the complete response is received.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Image Generation
&lt;/h3&gt;

&lt;p&gt;Apiction supports image generation from any OpenAI-compatible platform. For some other platforms, like Pollinations (though their recent updates now enable image generation via OpenAI-compatible endpoints), the image generation is supported via custom adapters. &lt;/p&gt;

&lt;p&gt;You switch the model type in the tab settings to &lt;code&gt;text-to-image&lt;/code&gt;, configure your endpoint and API key, and start generating.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Web Search and Tool Calling via MCP Servers
&lt;/h3&gt;

&lt;p&gt;Apiction integrates with the &lt;strong&gt;Model Context Protocol (MCP)&lt;/strong&gt;, a standard for connecting AI models to external tools and data sources via JSON-RPC.&lt;/p&gt;

&lt;p&gt;In practice, this means you can point a tab at a locally running MCP server (a web search tool, a database query tool, a file reader, whatever you have set up) and the AI model will use those tools autonomously when it decides they are necessary. &lt;/p&gt;

&lt;p&gt;It discovers the available tools at the start of a conversation, injects them into the request, and then executes the tool calls the model makes, up to five rounds of back-and-forth tool execution per message, before returning the final response to you.&lt;/p&gt;

&lt;p&gt;As indicated previously, each tab has its own tool configuration, so one tab can have web search enabled while another has none. The model decides when to invoke a tool and when to just respond directly.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Converse With Any AI Model From Any Provider
&lt;/h3&gt;

&lt;p&gt;This is arguably the core premise of Apiction. It natively supports &lt;strong&gt;OpenAI, OpenRouter, HuggingFace, Together.ai, Groq, Pollinations, Fireworks.ai&lt;/strong&gt;, and anything that speaks the OpenAI-compatible API format, which covers a large chunk of the ecosystem. &lt;/p&gt;

&lt;p&gt;For providers that do not follow that format, some providers are still supported via custom adapters and in future releases, more adapters will be added to cover other edge platforms as well.&lt;/p&gt;

&lt;p&gt;Apiction's internal architecture is built this way. The core of the application knows nothing about OpenAI or Anthropic or HuggingFace. All provider-specific logic lives in isolated adapters. &lt;/p&gt;

&lt;p&gt;When you configure an endpoint in a tab, the adapter selection is automatic based on the URL. This means adding a new provider is a matter of writing one file without touching anything else in the codebase.&lt;/p&gt;

&lt;p&gt;For end users, this simply means: if a new model drops somewhere, you can use it immediately, as long as you have the API key and endpoint.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Rolling Summary for Long Conversations
&lt;/h3&gt;

&lt;p&gt;Token limits are a real constraint. A long conversation will eventually exceed the context window of whatever model you are using.&lt;/p&gt;

&lt;p&gt;Apiction handles this with a rolling summarization system. After every set number of messages in a tab, the older portion of the conversation is automatically summarized using a summarization model for that tab. &lt;/p&gt;

&lt;p&gt;When building context for the next request, that summary is injected as a system message, so the model retains the context of what happened earlier without needing the raw message history.&lt;/p&gt;

&lt;p&gt;The summaries are cumulative, each new batch is merged into the existing summary rather than replacing it, so context is preserved across multiple summarization passes as well as there exists only one combined summary. The summarization model is configurable per tab, so you can choose a smaller, cheaper model for summarization and a larger one for conversation if you want.&lt;/p&gt;




&lt;h2&gt;
  
  
  For Developers
&lt;/h2&gt;

&lt;h3&gt;
  
  
  6. Raw Request and Response Debug Console
&lt;/h3&gt;

&lt;p&gt;Every tab has a debug mode that, when enabled, shows you the raw request payload sent to the provider and the raw response received back. This can be valuable if you are-&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Debugging a custom adapter or a new provider integration&lt;/li&gt;
&lt;li&gt;Verifying that your system prompt and message history are being formatted correctly&lt;/li&gt;
&lt;li&gt;Checking if tool call data is making it into the request payload&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It is per-tab and off by default, so it does not clutter the interface during normal use. &lt;/p&gt;

&lt;h3&gt;
  
  
  7. Performance Stats: TTFT, Total Time, Token Counts
&lt;/h3&gt;

&lt;p&gt;Below each response, when debug mode is enabled, you get:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Time to First Token (TTFT)&lt;/strong&gt; — how long from sending the request until the first token starts streaming back&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Total response time&lt;/strong&gt; — wall clock time from request to last token&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Input and output token counts&lt;/strong&gt; — pulled from the usage field of the response&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;TTFT is a meaningful metric for streaming models. Two providers serving the same model can have wildly different TTFT values depending on their infrastructure, load, and whether they are doing any preprocessing on your request. Total time is useful, but TTFT tells you more about latency.&lt;/p&gt;

&lt;h3&gt;
  
  
  8. Cross-Provider Model Comparison
&lt;/h3&gt;

&lt;p&gt;This is the most useful developer feature. If you are building an application on top of a specific model and relying on a certain level of reasoning quality, the provider you choose matters.&lt;/p&gt;

&lt;p&gt;In the Apiction, because each tab is independently configured, you can open multiple tabs, point them at different providers, set the same model on each, and send them the same prompt. You can then compare:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Response quality&lt;/li&gt;
&lt;li&gt;Response time and TTFT&lt;/li&gt;
&lt;li&gt;How the model behaves differently (or identically) across providers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For example, you can test and "gauge" if any provider is running a quantized model than the one advertised. Quantized models can be significantly cheaper and faster, but they often have reduced reasoning capabilities and can make more mistakes, especially on complex tasks. &lt;/p&gt;

&lt;p&gt;You can surface this with some targeted prompts. Ask the model to perform a precise multi-step arithmetic calculation or a logically dense reasoning problem. A full-precision model and a heavily quantized version of the same model will often diverge on these tasks or diverge in their confidence and the details of their reasoning. &lt;/p&gt;

&lt;p&gt;If two providers claim to be serving the same model but the responses differ significantly on a factual or mathematical problem, that can be a signal.&lt;/p&gt;




&lt;h2&gt;
  
  
  A Note on Privacy and Setup
&lt;/h2&gt;

&lt;p&gt;All of your conversations, settings, and summaries are stored in your browser's IndexedDB. &lt;/p&gt;

&lt;p&gt;The PHP backend it ships with is only there because many AI provider APIs block direct browser requests due to CORS. The backend is a thin proxy, it forwards your request, gets the response, and returns it. If a provider supports CORS directly, like Openrouter, you can enable direct requests in settings and skip the proxy entirely.&lt;/p&gt;

&lt;p&gt;You can also run it locally with just &lt;code&gt;php -S localhost:8000 -t public_html&lt;/code&gt; if you have PHP available, or use it via &lt;a href="https://apiction.site" rel="noopener noreferrer"&gt;apiction.site&lt;/a&gt; if you want to skip the setup.&lt;/p&gt;




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

&lt;p&gt;Apiction is for people who use AI models via different API providers, test new models, build on top of APIs, or just want more visibility into what is actually happening under the hood when they send a message. My intention was to build something like Postman but for AI APIs, and which can provide general usage features as well.&lt;/p&gt;

&lt;p&gt;If you're spending a meaningful amount of time working with AI APIs, it is worth having a workspace that keeps up.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>api</category>
      <category>tooling</category>
    </item>
    <item>
      <title>All Methods of Persistent Browser Storage</title>
      <dc:creator>Arunish</dc:creator>
      <pubDate>Sun, 07 Dec 2025 20:43:44 +0000</pubDate>
      <link>https://forem.com/arunish/all-methods-of-persistent-browser-storage-5ae7</link>
      <guid>https://forem.com/arunish/all-methods-of-persistent-browser-storage-5ae7</guid>
      <description>&lt;p&gt;Modern web applications are becoming increasingly powerful, blurring the line between websites and native desktop or mobile applications.&lt;/p&gt;

&lt;p&gt;A huge part of this power comes from the ability to save data directly in the user's browser. &lt;/p&gt;

&lt;p&gt;Web browser provide us with many tools for persistent data storage like cookies, &lt;code&gt;localStorage&lt;/code&gt;, &lt;code&gt;sessionStorage&lt;/code&gt;, and &lt;code&gt;IndexedDB&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;There are some modern alternatives as well like the &lt;code&gt;Cache API&lt;/code&gt; and &lt;code&gt;CookieStore API&lt;/code&gt; which are better than legacy options like &lt;code&gt;localStorage&lt;/code&gt; as they are asynchronous and can work with service workers. &lt;/p&gt;

&lt;p&gt;Many of these options like &lt;code&gt;IndexedDB&lt;/code&gt; and &lt;code&gt;Cache API&lt;/code&gt; allow a developer to implement storage of things much more complex than simple key-value string pairs. This in turn creates offline functionality, faster load times, and a rich user experience.&lt;/p&gt;

&lt;p&gt;Let's take a look at all these various methods of persistent browser storage, their use cases, advantages, and limitations.&lt;/p&gt;

&lt;h2&gt;
  
  
  LocalStorage &amp;amp; SessionStorage
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;localStorage&lt;/code&gt; and &lt;code&gt;sessionStorage&lt;/code&gt; are part of the Web Storage API and provide simple key-value storage mechanisms.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;localStorage&lt;/code&gt;: Data stored here has no expiration time. It remains until explicitly deleted by the user or the application.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;sessionStorage&lt;/code&gt;: Data stored here is cleared when the page session ends, i.e., when the browser tab is closed.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Writing and reading data from both &lt;code&gt;localStorage&lt;/code&gt; and &lt;code&gt;sessionStorage&lt;/code&gt; is straightforward:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Storing data in localStorage&lt;/span&gt;
&lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;key&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;value&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Retrieving data from localStorage&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;key&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Storing data in sessionStorage&lt;/span&gt;
&lt;span class="nx"&gt;sessionStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;key&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;value&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Retrieving data from sessionStorage&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sessionValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;sessionStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;key&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Both &lt;code&gt;localStorage&lt;/code&gt; and &lt;code&gt;sessionStorage&lt;/code&gt; are synchronous, which means they can block the main thread, potentially leading to performance issues if used excessively.&lt;/p&gt;

&lt;p&gt;Further, because of their synchronous nature, they cannot be used with Service Workers. The data is stored as strings, so complex data structures need to be serialized (e.g., using JSON). &lt;/p&gt;

&lt;p&gt;Their storage limits are typically around 5-10MB per origin, which is sufficient for storing these string values.&lt;/p&gt;

&lt;h2&gt;
  
  
  CookieStore API
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;CookieStore API&lt;/code&gt; is a modern alternative to traditional cookies, providing an &lt;em&gt;asynchronous&lt;/em&gt; way to manage cookies in the browser. &lt;/p&gt;

&lt;p&gt;It allows developers to read, write, and delete cookies without blocking the main thread.&lt;/p&gt;

&lt;p&gt;Writing its code is mostly similar to traditional cookie operations. Here's a simple example of how to use the &lt;code&gt;CookieStore API&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Setting a cookie, inside some async function&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;cookieStore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;user_name&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;JohnDoe&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;maxAge&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3600&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Getting a cookie, inside some async function&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;cookieStore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;username&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;CookieStore API&lt;/code&gt; is particularly useful for applications that require frequent cookie access without the performance drawbacks of synchronous operations.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cache API
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;Cache API&lt;/code&gt; is a powerful tool for storing network requests and responses. &lt;/p&gt;

&lt;p&gt;It is primarily used in conjunction with Service Workers to enable offline capabilities and improve load times but can also be used independently.&lt;/p&gt;

&lt;p&gt;Unlike Cookies, &lt;code&gt;localStorage&lt;/code&gt;, and &lt;code&gt;sessionStorage&lt;/code&gt;, the &lt;code&gt;Cache API&lt;/code&gt; allows you to store or cache many different types of data (responses) other than just strings, like HTML, CSS, JavaScript files, images, etc.&lt;/p&gt;

&lt;p&gt;The storage limit also far exceeds them, though it varies by browser and device. For instance, on Chrome, it can go upto 60% of the available disk space.&lt;/p&gt;

&lt;p&gt;Here's a simple example of how to use the &lt;code&gt;Cache API&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Open a cache, inside some async function&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cache&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;caches&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;my-cache&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Cache a network request/response&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/user-data&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Or cache a custom response for a specific request&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;custom_resp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;value&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;put&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/config&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;custom_resp&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Retrieve a response from the cache, inside some async function&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/user-data&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;Cache API&lt;/code&gt; is ideal for applications that need to cache resources for offline use or to speed up load times by serving cached content.&lt;/p&gt;

&lt;h2&gt;
  
  
  IndexedDB
&lt;/h2&gt;

&lt;p&gt;Finally the most powerful and complex option for persistent browser storage is &lt;code&gt;IndexedDB&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;You can think of all the above options like a desk drawer of your cabinet. Its right beside you. You open it, put a labeled folder in or take a labeled folder out. Incredibly easy to use.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;IndexedDB&lt;/code&gt; on the other hand is like a full library, where you can store all types of books, documents, equipment and media. Further, all these items are stored in a structured manner, making it easy to search, retrieve, and manipulate them. &lt;/p&gt;

&lt;p&gt;&lt;code&gt;IndexedDB&lt;/code&gt; is asynchronous and can hold gigabytes of data. The exact limit depends on the user's browser and disk space. &lt;/p&gt;

&lt;p&gt;Because of all this power, &lt;code&gt;IndexedDB&lt;/code&gt; is a bit more complex to use. While it is asynchronous, it is &lt;strong&gt;not&lt;/strong&gt; promise-based but rather &lt;strong&gt;event-based&lt;/strong&gt;, which can make the code verbose and harder to read.&lt;/p&gt;

&lt;p&gt;If you have experience with databases, you'll find &lt;code&gt;IndexedDB&lt;/code&gt; familiar as it supports transactions, indexing, and complex queries.&lt;/p&gt;

&lt;p&gt;Here's a an example of how to use &lt;code&gt;IndexedDB&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// 1. Open a connection to the database. Version 1.&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;indexedDB&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;myAppDatabase&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// This event runs ONLY when the DB is first created or version is changed&lt;/span&gt;
&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onupgradeneeded&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="c1"&gt;// Create an object store (like a table) called "users" with "id" as the primary key&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userStore&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createObjectStore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;users&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;keyPath&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="c1"&gt;// Create a name index so we can search by name later&lt;/span&gt;
  &lt;span class="nx"&gt;userStore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createIndex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;unique&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onerror&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Database error:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onsuccess&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Database opened successfully&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// Now we can perform operations&lt;/span&gt;
  &lt;span class="nf"&gt;add_user&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Alice&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dark&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;add_user&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user_object&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// 2. Create a transaction for read/write access&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;transaction&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;transaction&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;users&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;readwrite&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userStore&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;transaction&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;objectStore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;users&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// 3. Make a request to add the object&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;userStore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user_object&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onsuccess&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;User added successfully!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onerror&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Error adding user:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is a simplified "raw" API example. In the real world, you'd almost always use a wrapper library like &lt;a href="https://github.com/jakearchibald/idb" rel="noopener noreferrer"&gt;idb by Jake Archibald&lt;/a&gt; to make this much cleaner with Promises.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion: When to Use What
&lt;/h2&gt;

&lt;p&gt;Here's a quick summary of when to use each storage method-&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;CookieStore API&lt;/code&gt;: A modern alternative to the traditional cookies. You'd want to use this for small pieces of data that &lt;em&gt;need to be sent to the server with every request automatically&lt;/em&gt;, like session identifiers.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;localStorage&lt;/code&gt;: For simple, non-sensitive key-value String pairs that needs to persist across sessions and is less than 5-10MB.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;sessionStorage&lt;/code&gt;: For key-value String pairs that only need to persist for the duration of a page session.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Cache API&lt;/code&gt;: For caching network requests and responses, especially for offline capabilities and faster load times.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;IndexedDB&lt;/code&gt;: For large amounts of structured data and complex queries. For example, &lt;em&gt;find all users with age &amp;gt; 25 and city = 'New York'&lt;/em&gt;. You can perform such database-like operations with &lt;code&gt;IndexedDB&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Thanks for reading!&lt;/p&gt;

&lt;p&gt;p.s. If you liked this article, check out my blog &lt;a href="https://newgenstack.com" rel="noopener noreferrer"&gt;NewGen Stack&lt;/a&gt; where I cover more modern web development topics and tools for content creation.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>browser</category>
      <category>programming</category>
    </item>
    <item>
      <title>JavaScript Promises &amp; Under-the-Hood Mechanics</title>
      <dc:creator>Arunish</dc:creator>
      <pubDate>Fri, 05 Dec 2025 12:04:06 +0000</pubDate>
      <link>https://forem.com/arunish/javascript-promises-under-the-hood-mechanics-6ad</link>
      <guid>https://forem.com/arunish/javascript-promises-under-the-hood-mechanics-6ad</guid>
      <description>&lt;p&gt;Promises, while simple in idea and concept, the way they are written or implemented in JavaScript is slightly confusing to many beginners or even experienced developers who come from other languages. &lt;/p&gt;

&lt;p&gt;Let's look at a typical asynchronous function-&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;increment_val&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;val&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;val1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_base_value&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; 
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;val2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;get_user_input&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// asynchronous task&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;final_val&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;val&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;val1&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;val2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;final_val&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I've written this intentionally in a verbose way to make our discussion easier. Now, at first glance, it may look like the function is returning whatever the &lt;code&gt;final_val&lt;/code&gt; is. But actually, this function is returning a Promise.&lt;/p&gt;

&lt;p&gt;Any function with an &lt;code&gt;async&lt;/code&gt; keyword at the beginning makes that function return a Promise. Even if there is no explicit return.&lt;/p&gt;

&lt;p&gt;To understand the concept better, let's consider a relatable real world analogy. Suppose you go to a coffee shop and place your order at the counter. After payment, the cashier gives you a receipt and asks the barista to prepare your brew.&lt;/p&gt;

&lt;p&gt;An important point to note here is that, after billing is performed, you are immediately given a receipt (the Promise), and not the actual coffee (the Result).&lt;/p&gt;

&lt;p&gt;It will take some time for your coffee to arrive, but you don't have to wait and block the queue. You are free to go and do other things, look around the shop, check emails etc. while your order is fulfilled.&lt;/p&gt;

&lt;p&gt;A Promise in JavaScript is exactly the same.&lt;/p&gt;

&lt;p&gt;When the execution reaches our &lt;code&gt;increment_val()&lt;/code&gt; function, it returns immediately with a Promise (the receipt). And not with the actual return &lt;code&gt;final_val&lt;/code&gt; (the coffee) yet.&lt;/p&gt;

&lt;p&gt;The promise will be "fulfilled" later. It will either resolve with that returned &lt;code&gt;final_val&lt;/code&gt; or reject if an error is encountered (like if the user input is NaN).&lt;/p&gt;

&lt;p&gt;What does the &lt;code&gt;await&lt;/code&gt; do here?&lt;br&gt;
We use the &lt;code&gt;await&lt;/code&gt; keyword to get the fulfilled value of a promise. You can only use &lt;code&gt;await&lt;/code&gt; inside an &lt;code&gt;async&lt;/code&gt; function. &lt;/p&gt;

&lt;h2&gt;
  
  
  Why we even need all these? Let's take a look under the hood
&lt;/h2&gt;

&lt;p&gt;In the small &lt;code&gt;increment_val()&lt;/code&gt; function we considered above, there is a task in that function which has to get an input value from the user. &lt;/p&gt;

&lt;p&gt;Since we don't know when the user will input that value, we have 2 options-&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Wait till the user inputs a value. This will make the JavaScript engine pause and not attend to other tasks.
OR&lt;/li&gt;
&lt;li&gt;Make the code block asynchronous. In the example above, we did this by writing &lt;code&gt;async&lt;/code&gt; keyword in front of the function.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;When the JavaScript engine executes our &lt;code&gt;async increment_val()&lt;/code&gt; function and it encounters &lt;code&gt;await get_user_input()&lt;/code&gt;-&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;It saves the state of that function (all local variable values and its lexical scope).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Pauses further execution of &lt;em&gt;that function&lt;/em&gt; only and exits the function context by returning with a Promise.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Meanwhile, the JavaScript engine returns control to the event loop and is now free to process other tasks.&lt;/p&gt;

&lt;p&gt;Once the promise returned by &lt;code&gt;get_user_input()&lt;/code&gt; is fulfilled, the JavaScript engine is notified. Who notifies it? The browser environment running outside it.&lt;/p&gt;

&lt;p&gt;The JS engine finishes whatever immediate task it was doing, comes back to the &lt;code&gt;increment_val()&lt;/code&gt; function, loads its saved state and resumes operations right where it left off.&lt;/p&gt;

&lt;p&gt;A very important point to note here is, while the JS engine (where our &lt;em&gt;code logic&lt;/em&gt; runs) is synchronous and single threaded, &lt;em&gt;the browser environment where it lives is not&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Many tasks are performed by the surrounding browser environment and even the underlying OS (like fetching network requests, timers, or disk I/O). These environments can be asynchronous and multi-threaded.&lt;/p&gt;

&lt;p&gt;The JS engine can offload many of its tasks to these environments. We often implement this by using the tools provided  by these environments through Web APIs like setTimeout, Fetch, CookieStore, etc.&lt;/p&gt;

&lt;p&gt;This is how the JavaScript engine, despite being single-threaded and synchronous itself, handles asynchronicity. It has essentially offloads the heavy lifting to the browser environment, while holding a Promise or "receipt" until the job is done.&lt;/p&gt;




&lt;p&gt;Understanding that &lt;code&gt;async&lt;/code&gt; functions always return a Promise and that &lt;code&gt;await&lt;/code&gt; is simply a mechanism to pause execution and offload work to the browser environment makes debugging complex applications much easier.&lt;/p&gt;

&lt;p&gt;There are some other ways of returning promises as well. Like using the constructor &lt;code&gt;new Promise((resolve, reject) =&amp;gt; { ... })&lt;/code&gt;, however using async/await syntax I find is easier to implement as they are written similar to other synchronous functions.&lt;/p&gt;

&lt;p&gt;Thanks for reading!&lt;/p&gt;

&lt;p&gt;p.s. If you liked this article, check out my blog &lt;a href="https://newgenstack.com" rel="noopener noreferrer"&gt;NewGen Stack&lt;/a&gt; where I cover more modern web development topics and tools for content creation.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>node</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
