<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Tips on Jonathan's Blog</title><link>https://jonathan-frere.com/tags/tips/</link><description>Recent content in Tips on Jonathan's Blog</description><generator>Hugo</generator><language>en-gb</language><copyright>This work is licensed under CC BY-SA 4.0</copyright><lastBuildDate>Sun, 21 Sep 2025 00:00:00 +0000</lastBuildDate><atom:link href="https://jonathan-frere.com/tags/tips/index.xml" rel="self" type="application/rss+xml"/><item><title>Storing Unwise Amounts of Data in JavaScript Bigints</title><link>https://jonathan-frere.com/posts/bigints-are-cool/</link><pubDate>Sun, 21 Sep 2025 00:00:00 +0000</pubDate><guid>https://jonathan-frere.com/posts/bigints-are-cool/</guid><description>&lt;p>This is a short note to document storing data in JS&amp;rsquo;s &lt;code>bigint&lt;/code> type. I tried this out in a project recently, and it&amp;rsquo;s not obviously a terrible idea, as long as you take into account all the caveats that make it only useful for very specific cases.&lt;/p>
&lt;h2 id="why">
 &lt;a href="#why">Why&lt;/a>
&lt;/h2>

&lt;p>This is a performance&lt;sup id="fnref:1">&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref">1&lt;/a>&lt;/sup> thing. In the project where I was exploring this, we had a large amount of objects representing configuration values. The possible configuration keys were the same, but different objects had different keys set. This approach was causing some issues:&lt;/p></description><content:encoded><![CDATA[<p>This is a short note to document storing data in JS&rsquo;s <code>bigint</code> type.  I tried this out in a project recently, and it&rsquo;s not obviously a terrible idea, as long as you take into account all the caveats that make it only useful for very specific cases.</p>
<h2 id="why">
  <a href="#why">Why</a>
</h2>

<p>This is a performance<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup> thing.  In the project where I was exploring this, we had a large amount of objects representing configuration values.  The possible configuration keys were the same, but different objects had different keys set.  This approach was causing some issues:</p>
<ul>
<li>Serialization and deserialization produced very large strings because of all the repeated keys.</li>
<li>Comparison/equality of objects was costly because of the number of keys.</li>
<li>We needed to do a lot of operations like &ldquo;find the subset of keys and values that are identical between all of these objects&rdquo;.  This was slow.</li>
<li>We often needed to update subsets of the items by adding, updating, or removing keys, so each object needed to be an independent clone.</li>
</ul>
<p>Originally, I planned on doing some sort of object interning to reduce the number of objects we needed to keep in memory at any one time.  We would keep only one copy of each unique configuration item, and just reference it in multiple locations.  The (now dead) <a href="https://github.com/tc39/proposal-record-tuple">Records and Tuples</a> proposal would have been really useful here, and its replacement, <a href="https://github.com/tc39/proposal-composites">Composites</a> looks like it might help but I didn&rsquo;t want to tie myself to an incomplete early-stage proposal.  So if I went down this route, I&rsquo;d be building something myself.</p>
<p>While looking all this up, I found Justin Fagnani&rsquo;s article <a href="https://justinfagnani.com/2024/11/09/composite-map-keys-in-javascript-with-bitsets/">Composite Map Keys in JavaScript with Bitsets</a>, which is mostly unrelated to what I&rsquo;m doing here, but did make me think of using bigints in the first place.</p>
<h2 id="how">
  <a href="#how">How</a>
</h2>

<p>The basic idea is:</p>
<ol>
<li>Define a bunch of fields, how they should be interpreted, their size, etc.  E.g. <code>{name: &quot;size&quot;, kind: &quot;uint&quot;, bits: 8}</code> to represent a number stored as a u8.  You also need to know the offset of each field, this can be calculated from the index of each field and the number of bits in the preceding fields.</li>
<li>Add functions <code>getBits(bigint, offset, bits)</code> which does bitshifting to fetch the relevant bits from the <code>bigint</code> backing store, and <code>setBits(bigint, offset, bits, value)</code> which does the opposite</li>
<li>For each field, add getters and setters that do the type conversions from e.g. JS <code>number</code> to u8.</li>
</ol>
<p>Honestly, I was impressed by how well Claude Sonnet handled this stuff.  It didn&rsquo;t produce the tidiest code, nor did it find the clearest ways of doing many things, but the basic bit-bashing was largely correct, and I wrote a lot of tests to confirm that it was working in the way I wanted.</p>
<p>In this use-case, not all keys are present at all times.  To handle this, I added an extra store <code>present</code> alongside the <code>bigint</code> backing store that was a simple bitfield where if bit <code>i</code> was 1 in the <code>present</code> store, then the <code>i</code>th field had been set in the main backing store.  Deleting a field meant simply clearing the <code>i</code>th bit.</p>
<h2 id="benefits">
  <a href="#benefits">Benefits</a>
</h2>

<ul>
<li>The memory usage of the object is about as compact as it&rsquo;s possible to be.  Booleans take up a single bit, colours can be stored as u32 values (for rgba), fields that were previously string enums are now just a couple of bits wide, etc.</li>
<li>Deserialization is very quick (basically just <code>BigInt(&quot;0x&quot; + value)</code> to convert a hexadecimal string back into our backing store).  Serialization is slightly slower because I wanted to ensure that unset fields were zeroed-out first, to ensure consistent representations.  The resulting string is pretty compact.</li>
<li>Lots of operations can take advantage of the <code>present</code> bits to optimise what they&rsquo;re doing.  For example, when checking equality, we can first check that the two <code>present</code> bits are equal to make sure that the same fields are set in both cases.  When finding the intersection of two values, we can first <code>AND</code> the present bits together, and check only the fields that are set in both values.</li>
</ul>
<p>This whole thing is surprisingly usable.</p>
<h2 id="drawbacks">
  <a href="#drawbacks">Drawbacks</a>
</h2>

<ul>
<li>Fields need to have a max width.  For example, you can&rsquo;t store an arbitrary string in the <code>bigint</code>, because you don&rsquo;t know when it will end.  If you need dynamically-sized data, then this isn&rsquo;t going to work.</li>
<li>Bit operations on <code>bigint</code>s is slow.  I mean, all things are relative, but in general, gets and sets will be faster with plain old JS objects.  HOWEVER: if you have a lot of smaller fields, you can cheat a bit and use a <code>number</code> backing store, or use a combination of a <code>number</code> store for smaller fields and a <code>bigint</code> store for larger fields.  Bit operations on <code>number</code> objects are very fast, and in my tests, gets and sets were roughly the same speed as getting/setting regular JS object fields.</li>
<li>The code is going to be <em>way</em> more complex.  Expect to write a whole bunch of tests that basic things like getting and setting a property work.  I suspect a good library or layer of abstraction could help here, but, having only done this the once, I don&rsquo;t know what that abstraction would look like yet.</li>
</ul>
<p>This might not sound like a lot of drawbacks, but they&rsquo;re all very significant compared to the more niche benefits of this approach.  I wouldn&rsquo;t recommend doing this in most cases.</p>
<h2 id="is-it-worth-it">
  <a href="#is-it-worth-it">Is It Worth It?</a>
</h2>

<p>I&rsquo;m not entirely sure yet.  This is a bit of an experimental side project at the moment, just playing around with one way of optimising one component of the main project I&rsquo;m working on.  I need to see how it feels to use this approach in practice.  The goal is not necessarily that <code>bigint</code>s by themselves will make things better, but that they&rsquo;ll enable other optimisations by having much quicker equality checking, etc, so I need to try out those other optimisations and see the results.  If you&rsquo;re reading this in a few months and still curious, reach out to me on Bluesky or something and ask me how it&rsquo;s going, and then I can update this blog post with the results.</p>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>Note: performance as in &ldquo;speed, efficiency&rdquo;, not performance as in &ldquo;performance art&rdquo;.  Although I would be interested in using obtuse programming techniques as performance art.&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content:encoded></item><item><title>This Overly Long Variable Name Could Have Been a Comment</title><link>https://jonathan-frere.com/posts/names-vs-comments/</link><pubDate>Tue, 01 Jul 2025 00:00:00 +0000</pubDate><guid>https://jonathan-frere.com/posts/names-vs-comments/</guid><description>&lt;p>Here&amp;rsquo;s a belief I&amp;rsquo;ve held for a while but only recently been able to put into words: explanatory comments are often easier to understand than explanatory variable or function names.&lt;/p>
&lt;p>Consider a complicated expression with multiple sub-expressions. This expression is going to be difficult for the next person reading this code to decipher; we should make it easier for them.&lt;/p>
&lt;p>There are a couple of ways to solve this. We could break down the expression into sub-expressions, and assign those sub-expressions to intermediate variables. Or we could pull the expression out into its own dedicated function. In each case, the goal is to give either part or all of the expression a dedicated name. This name helps the next reader to understand the purpose or meaning of the expression.&lt;/p></description><content:encoded><![CDATA[<p>Here&rsquo;s a belief I&rsquo;ve held for a while but only recently been able to put into words: explanatory comments are often easier to understand than explanatory variable or function names.</p>
<p>Consider a complicated expression with multiple sub-expressions.  This expression is going to be difficult for the next person reading this code to decipher; we should make it easier for them.</p>
<p>There are a couple of ways to solve this. We could break down the expression into sub-expressions, and assign those sub-expressions to intermediate variables. Or we could pull the expression out into its own dedicated function. In each case, the goal is to give either part or all of the expression a dedicated name.  This name helps the next reader to understand the purpose or meaning of the expression.</p>
<p>Unfortunately, <a href="https://steveklabnik.com/writing/against-names/">names are hard</a>.  A good, meaningful name puts the next reader in exactly the right frame of mind to understand what is going on.  A bad name can confuse the next reader and make the code less legible than before.  And finding the right name is a difficult task.  It can&rsquo;t be too long and unwieldy — being too verbose makes it hard to communicate effectively, as anyone who&rsquo;s worked with German bureaucracy can tell you.  On the other hand, it can&rsquo;t be too short or generic — naming everything <code>x</code> or <code>var</code> will rarely help future readers.</p>
<p>Sometimes, though, I can&rsquo;t find a good, obvious name.  In these cases, rather than trying to force one, I instead write a comment.  A comment gives you more space to work with, which means it can be much more exact and precise than a single name.  You can use a comment to remove potential ambiguities that a more generic name might have.  A comment also allows you the chance to provide more &ldquo;why&rdquo;-type explanation rather than just describing the &ldquo;what&rdquo;.</p>
<p>A good name is normally far better than a comment, but good names are hard to come by.  If you&rsquo;re struggling to find the right name for a particular chunk of code, consider whether the context would be better explained as a comment.<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup></p>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>As a brief postscript, a note about comments going out of date.  This certainly happens!  But the same is also true of names, which can easily end up out of date after a couple of rounds of refactoring.  In my experience, comments often contain more details, which means they can become (at least partially) outdated more easily, but in either case, it&rsquo;s important to check names and comments when doing refactoring work.&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content:encoded></item><item><title>Side Effects in SolidJS</title><link>https://jonathan-frere.com/posts/side-effects-in-solidjs/</link><pubDate>Tue, 27 May 2025 00:00:00 +0000</pubDate><guid>https://jonathan-frere.com/posts/side-effects-in-solidjs/</guid><description>&lt;p>If you’re used to React, you’re probably used to using &lt;code>useEffect&lt;/code> to run side-effectful code, such as integrating with third-party libraries or setting up &lt;code>MutationObserver&lt;/code>s&lt;sup id="fnref:1">&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref">1&lt;/a>&lt;/sup>. SolidJS also has &lt;code>createEffect&lt;/code>, which works very similarly to &lt;code>useEffect&lt;/code>, but it also has some other functions, and I’ve noticed that people getting started with SolidJS often aren’t sure which function to use for any given side-effects.&lt;/p>
&lt;p>If you’re in that boat, then here is the answer in tabular form:&lt;/p></description><content:encoded><![CDATA[<p>If you’re used to React, you’re probably used to using <code>useEffect</code> to run side-effectful code, such as integrating with third-party libraries or setting up <code>MutationObserver</code>s<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>.  SolidJS also has <code>createEffect</code>, which works very similarly to <code>useEffect</code>, but it also has some other functions, and I’ve noticed that people getting started with SolidJS often aren’t sure which function to use for any given side-effects.</p>
<p>If you’re in that boat, then here is the answer in tabular form:</p>
<table>
  <thead>
      <tr>
          <th style="text-align: right"></th>
          <th style="text-align: center">runs immediately</th>
          <th style="text-align: center">runs on mount</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td style="text-align: right"><strong>is reactive<br>(runs multiple times)</strong></td>
          <td style="text-align: center"><code>createRenderEffect</code></td>
          <td style="text-align: center"><code>createEffect</code></td>
      </tr>
      <tr>
          <td style="text-align: right"><strong>is not reactive<br>(only runs once)</strong></td>
          <td style="text-align: center">no function needed</td>
          <td style="text-align: center"><code>onMount</code></td>
      </tr>
  </tbody>
</table>
<p>In this post, I’ll unpack this table and explain what it means in a bit more detail.</p>
<h2 id="what-are-side-effects">
  <a href="#what-are-side-effects">What are side effects?</a>
</h2>

<p>Side effects in this context is code that:</p>
<ul>
<li>interacts with the page (i.e. isn’t deriving new values from existing inputs)</li>
<li>isn’t handled by the framework itself (e.g. adding <code>onClick</code> handlers to a button via JSX, or using async/suspense).</li>
</ul>
<p>So for the purposes of this blog post, something like this might be a side effect:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-tsx" data-lang="tsx"><span class="line"><span class="cl"><span class="c1">// attach a global event listener from
</span></span></span><span class="line"><span class="cl"><span class="c1">// inside a particular component
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="nb">document</span><span class="p">.</span><span class="nx">addEventHandler</span><span class="p">(</span><span class="s2">&#34;keydown&#34;</span><span class="p">,</span> <span class="p">()</span> <span class="o">=&gt;</span> <span class="p">{</span> <span class="cm">/* ... */</span> <span class="p">});</span>
</span></span></code></pre></div><p>But these probably aren’t side effects:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-tsx" data-lang="tsx"><span class="line"><span class="cl"><span class="c1">// derive the `fullName()` signal by
</span></span></span><span class="line"><span class="cl"><span class="c1">// combining a `firstName()` and `lastName()`
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kr">const</span> <span class="nx">fullName</span> <span class="o">=</span> <span class="p">()</span> <span class="o">=&gt;</span> <span class="nx">firstName</span><span class="p">()</span> <span class="o">+</span> <span class="s2">&#34; &#34;</span> <span class="o">+</span> <span class="nx">lastName</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// attach an event listener to a particular
</span></span></span><span class="line"><span class="cl"><span class="c1">// element using JSX
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">&lt;</span><span class="nt">input</span> <span class="na">onKeyDown</span><span class="o">=</span><span class="p">{()</span> <span class="o">=&gt;</span> <span class="p">{</span> <span class="cm">/* ... */</span> <span class="p">}}</span> <span class="p">/&gt;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// this does have side effects, but for the purposes of
</span></span></span><span class="line"><span class="cl"><span class="c1">// this post, those side effects are handled by SolidJS
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kr">const</span> <span class="p">[</span><span class="nx">resource</span><span class="p">]</span> <span class="o">=</span> <span class="nx">createResource</span><span class="p">(()</span> <span class="o">=&gt;</span> <span class="nx">fetch</span><span class="p">(</span><span class="cm">/* ... */</span><span class="p">));</span>
</span></span></code></pre></div><h2 id="are-my-side-effects-reactive">
  <a href="#are-my-side-effects-reactive">Are my side effects reactive?</a>
</h2>

<p>There are broadly two types of side effect:</p>
<ul>
<li>Side effects that run once over a component’s entire lifecycle — i.e. some code that should run once when each instance of the component is first rendered, and then cleaned up when the component is unmounted, but never between.  These side effects are <em>not reactive</em>.</li>
<li>Side effects that run multiple times whenever an input changes — i.e. code that will regularly be rerun during the lifetime of the component<sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup>.</li>
</ul>
<p>For example, the global <code>keydown</code> handler from before will probably only need to run once: we set the handler when the component is mounted, and then remove it when we’re ready to clean the component up.  However, the classic <a href="https://overreacted.io/making-setinterval-declarative-with-react-hooks/"><code>useInterval</code></a> hook needs to use reactive side-effects: whenever the input parameters change, we need to clean up the old <code>setInterval</code> handler and create a new one.</p>
<h2 id="when-should-my-side-effects-run">
  <a href="#when-should-my-side-effects-run">When should my side effects run?</a>
</h2>

<p>SolidJS’s side effects can be triggered at two different times:</p>
<ul>
<li>Immediately, as the component is being created</li>
<li>Later, once the component has been mounted to the DOM and is ready to be used</li>
</ul>
<p>Some things only make sense once the component has been mounted: any code that needs to access <a href="https://docs.solidjs.com/concepts/refs"><code>ref</code></a>, for example, should run after the element has been created and attached to the DOM<sup id="fnref:3"><a href="#fn:3" class="footnote-ref" role="doc-noteref">3</a></sup>.</p>
<p>Some things are not so clear-cut though.  For example <code>setInterval</code> doesn’t require any access to the DOM or to any particular elements, so it might make sense to put it in the “run immediately” category.  In practice, however, <code>setInterval</code> should normally only run once the component has been mounted.  Why?</p>
<p>The answer is server-side rendering.  When a component is rendered server-side, the DOM is never mounted per-se, so side effects that run only once mounted are never run.  However side effects that run immediately <em>are</em> run, because they will probably affect how the component will be rendered.  In fact, that’s normally the point of having them run immediately in the first place, so they can affect rendering!</p>
<p>If we put <code>setInterval</code> in the “run immediately” category, then it will be run on the server.  But the render code will never wait for the interval handler to actually start, it’ll just carry on generating HTML and sending it to the client.  And once the HTML has been generated, the component will be unmounted, the <code>setInterval</code> handler will be cleared, and the code in it probably won’t have even had the chance to run once, let alone affect how the code gets rendered<sup id="fnref:4"><a href="#fn:4" class="footnote-ref" role="doc-noteref">4</a></sup>.</p>
<p>This won’t break anything (as long as the interval is correctly cleared), but it is a useless call to <code>setInterval</code>, and a useless resource that needs to be allocated and cleaned up at some point.  Therefore, if you’ve got a side effect and you’re sure it won’t affect rendering, consider running it only once the DOM has been mounted.</p>
<h2 id="bringing-it-together-as-a-table">
  <a href="#bringing-it-together-as-a-table">Bringing it together as a table</a>
</h2>

<p>If we combine the two questions above, we end up with four different cases, as shown in the table I showed earlier:</p>
<table>
  <thead>
      <tr>
          <th style="text-align: right"></th>
          <th style="text-align: center">runs immediately</th>
          <th style="text-align: center">runs on mount</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td style="text-align: right"><strong>is reactive<br>(runs multiple times)</strong></td>
          <td style="text-align: center"><code>createRenderEffect</code></td>
          <td style="text-align: center"><code>createEffect</code></td>
      </tr>
      <tr>
          <td style="text-align: right"><strong>is not reactive<br>(only runs once)</strong></td>
          <td style="text-align: center">no function needed</td>
          <td style="text-align: center"><code>onMount</code></td>
      </tr>
  </tbody>
</table>
<p>To finish up, let’s look at those four cases individually.</p>
<ul>
<li><code>createEffect</code>: The first run always happens after the component is mounted.  After that, if a signal used in the body of the effect changes, the effect will be rerun.  If no signals are used in the body, then this behaves the same as <code>onMount</code>.</li>
<li><code>onMount</code>: As the name says, this also happens after the component is mounted, but it is <em>not</em> reactive.  This is good for side effects that only need to run once that use the DOM.</li>
<li><code>createRenderEffect</code>: Reactively, this behaves the same as <code>createEffect</code>, but the first run will happen <em>immediately</em> (i.e. synchronously before the <code>createRenderEffect</code> is completed).  Similarly to <code>createEffect</code>, if no signals are used in the body of the effect, then this behaves the same as running the code in the body of the component.</li>
<li><em>no function needed</em>: Remember that the body of your component will only get called once during the component’s lifetime, so non-reactive side-effects that need to run immediately (such as instantiating a third-party library, or using <code>createUniqueId</code>) can be called as part of that body.</li>
</ul>
<h2 id="addendum-oncleanup">
  <a href="#addendum-oncleanup">Addendum: <code>onCleanup</code></a>
</h2>

<p>A lot of side effects require some sort of cleanup to happen later — for example, starting a <code>setInterval</code> timer requires cleaning up that timer when it’s no longer needed.  For that, SolidJS provides the <code>onCleanup</code> function.</p>
<p>As a rule of thumb, <code>onCleanup</code> can be called wherever there is a scope that would get cleaned up at some point.  For example, once a component is no longer being rendered, it needs to be cleaned up and removed from the DOM.  By calling <code>onCleanup</code> in the component body, you can add an extra callback that will be called when that happens.</p>
<p>For reactive effects (<code>createRenderEffect</code>/<code>createEffect</code>), calling <code>onCleanup</code> inside the effect callback will schedule a function to run when the effect is re-run, i.e. when a signal triggers the effect to restart, all <code>onCleanup</code> functions will get called, and then the new effect is run.</p>
<p>In general, put your <code>onCleanup</code> calls inside the function you use to create your side effect in the first place.  For example:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-tsx" data-lang="tsx"><span class="line"><span class="cl"><span class="c1">// NO!  Don&#39;t do this!
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="nx">onMount</span><span class="p">(()</span> <span class="o">=&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="cm">/* some side effect */</span>
</span></span><span class="line"><span class="cl"><span class="p">});</span>
</span></span><span class="line"><span class="cl"><span class="nx">onCleanup</span><span class="p">(()</span> <span class="o">=&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="cm">/* some clean up */</span>
</span></span><span class="line"><span class="cl"><span class="p">});</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// ----
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>
</span></span><span class="line"><span class="cl"><span class="c1">// YES!  Do this!
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="nx">onMount</span><span class="p">(()</span> <span class="o">=&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="cm">/* some side effect */</span>
</span></span><span class="line"><span class="cl">  <span class="nx">onCleanup</span><span class="p">(()</span> <span class="o">=&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="cm">/* some clean up */</span>
</span></span><span class="line"><span class="cl">  <span class="p">});</span>
</span></span><span class="line"><span class="cl"><span class="p">});</span>
</span></span></code></pre></div><p>This is because generally you only want the <code>onCleanup</code> to run if the side effect was called in the first place.  As mentioned earlier, functions like <code>onMount</code> and <code>createEffect</code> will not run during SSR, but if the <code>onCleanup</code> isn’t inside one of those functions, then it will still be called during SSR, doing unexpected things.</p>
<h2 id="addendum-avoiding-effects">
  <a href="#addendum-avoiding-effects">Addendum: Avoiding effects</a>
</h2>

<p>At the start, I made the comparison to React’s <code>useEffect</code>, and in a footnote pointed out that in modern React, <code>useEffect</code> is generally discouraged — there’s often a better way.</p>
<p>In SolidJS, <code>createEffect</code> doesn’t behave in quite such surprising ways as <code>useEffect</code>, thanks in large part to the automatic dependency tracking that means that the effect normally re-runs when you’d expect it to re-run.  However, it’s still a good idea to look out for cases where you can replace <code>createEffect</code> with a better option.  When I look at <code>createEffect</code> calls, these are the things I’m looking out for:</p>
<ul>
<li>Is a signal setter being used in the body of the effect?  If so, the effect can almost certainly be replaced by <code>createMemo</code> or another form of computed signal.</li>
<li>Is an async function being called in the effect?  If so, it might be worth using <code>createResource</code> (or <code>createAsync</code> from Solid Router) instead, as this will handle some of the boilerplate for you, as well as integrating with the suspense mechanism.</li>
<li>Is the effect setting an event handler on a DOM element?  If so, use the <code>on*</code> handlers in JSX instead.  This seems obvious, but I’ve written this sort of code before, only to realise later that I’d missed an obvious and easier solution.</li>
<li>Is the function body reactive and/or would the effect work better if it was run immediately?  As discussed in this article, other functions for running side effects are available.</li>
<li>Is there a function that already handles this case in a <a href="https://primitives.solidjs.community/">Solid Primitives</a> package, or can you write your own wrapper around the effect to encapsulate it a bit better?  This one isn’t really about getting rid of effects, but rather hiding them somewhere else.  But encapsulation is good, and the Solid Primitives functions are generally useful, even if you’re just looking at the source code to get a hint of how to do something.</li>
</ul>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>You’re probably also used to people telling you not to use <code>useEffect</code> if you can avoid it.  That’s often good advice in SolidJS as well, although perhaps not to the same extent — I’ll discuss that a bit at the end of this post.&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:2">
<p>Comparison with React time again: React does <em>not</em> explicitly distinguish between these two cases.  <code>useEffect</code> is always reactive, albeit reactive based on the explicit deps array (unlike SolidJS where dependency tracking happens automatically).  However, the “run once” case is usually modelled by an empty deps array (i.e. <code>[]</code>), and the “run many times” case is modelled by adding dependencies to that array.&#160;<a href="#fnref:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:3">
<p>Note that code that <em>sets up</em> refs should run immediately, and not later.  This distinction is very rarely important — as a general rule, if you’re accessing a ref, you’ll want the code doing that to run after the DOM has been mounted.&#160;<a href="#fnref:3" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:4">
<p>My inner pedant wants you to know that with async rendering/suspense, it is possible to manufacture situations where rendering will wait until <code>setInterval</code> has been called at least once.  I can’t think of any good reason why you should do this, but technically this paragraph isn’t quite true.&#160;<a href="#fnref:4" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content:encoded></item><item><title>Accessing Fastify Sessions via tRPC Websockets</title><link>https://jonathan-frere.com/posts/trpc-fastify-websockets/</link><pubDate>Tue, 15 Apr 2025 00:00:00 +0000</pubDate><guid>https://jonathan-frere.com/posts/trpc-fastify-websockets/</guid><description>&lt;p>This is a quick post to point out a potential issue that might catch you out with using Fastify&amp;rsquo;s sessions mechanism alongside tRPC&amp;rsquo;s websockets transport, and how I&amp;rsquo;ve fixed it in my projects.&lt;/p>
&lt;p>The problem happens with an application that looks something like this:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-typescript" data-lang="typescript">&lt;span class="line">&lt;span class="cl">&lt;span class="kr">const&lt;/span> &lt;span class="nx">app&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nx">Fastify&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nx">app&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">register&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nx">ws&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nx">app&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">register&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nx">fastifyCookie&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nx">app&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">register&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nx">fastifySession&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="p">{&lt;/span> &lt;span class="nx">secret&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s2">&amp;#34;...&amp;#34;&lt;/span> &lt;span class="p">});&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nx">app&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">register&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nx">fastifyTRPCPlugin&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">prefix&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s2">&amp;#34;/trpc&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">useWSS&lt;/span>: &lt;span class="kt">true&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">trpcOptions&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">router&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">onError&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">createContext&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="p">({&lt;/span> &lt;span class="nx">req&lt;/span> &lt;span class="p">})&lt;/span> &lt;span class="o">=&amp;gt;&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">console&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">log&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nx">req&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">session&lt;/span>&lt;span class="p">);&lt;/span> &lt;span class="c1">// logs &amp;#34;undefined&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="k">return&lt;/span> &lt;span class="p">{};&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">});&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>The &lt;code>useWSS&lt;/code> parameter passed to the tRPC plugin means that it can handle both standard HTTP requests and a persistent websocket connection. Theoretically, both of these kinds of requests get handled by Fastify first, and therefore both should be initialised with a session object&lt;sup id="fnref:1">&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref">1&lt;/a>&lt;/sup>. In practice, though, the &lt;code>session&lt;/code> field is missing on all websocket-based connections, but present for all HTTP-based connections.&lt;/p></description><content:encoded><![CDATA[<p>This is a quick post to point out a potential issue that might catch you out with using Fastify&rsquo;s sessions mechanism alongside tRPC&rsquo;s websockets transport, and how I&rsquo;ve fixed it in my projects.</p>
<p>The problem happens with an application that looks something like this:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-typescript" data-lang="typescript"><span class="line"><span class="cl"><span class="kr">const</span> <span class="nx">app</span> <span class="o">=</span> <span class="nx">Fastify</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nx">app</span><span class="p">.</span><span class="nx">register</span><span class="p">(</span><span class="nx">ws</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="nx">app</span><span class="p">.</span><span class="nx">register</span><span class="p">(</span><span class="nx">fastifyCookie</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="nx">app</span><span class="p">.</span><span class="nx">register</span><span class="p">(</span><span class="nx">fastifySession</span><span class="p">,</span> <span class="p">{</span> <span class="nx">secret</span><span class="o">:</span> <span class="s2">&#34;...&#34;</span> <span class="p">});</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nx">app</span><span class="p">.</span><span class="nx">register</span><span class="p">(</span><span class="nx">fastifyTRPCPlugin</span><span class="p">,</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nx">prefix</span><span class="o">:</span> <span class="s2">&#34;/trpc&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="nx">useWSS</span>: <span class="kt">true</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="nx">trpcOptions</span><span class="o">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nx">router</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nx">onError</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nx">createContext</span><span class="o">:</span> <span class="p">({</span> <span class="nx">req</span> <span class="p">})</span> <span class="o">=&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">req</span><span class="p">.</span><span class="nx">session</span><span class="p">);</span> <span class="c1">// logs &#34;undefined&#34;
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>      <span class="k">return</span> <span class="p">{};</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl">  <span class="p">},</span>
</span></span><span class="line"><span class="cl"><span class="p">});</span>
</span></span></code></pre></div><p>The <code>useWSS</code> parameter passed to the tRPC plugin means that it can handle both standard HTTP requests and a persistent websocket connection. Theoretically, both of these kinds of requests get handled by Fastify first, and therefore both should be initialised with a session object<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>. In practice, though, the <code>session</code> field is missing on all websocket-based connections, but present for all HTTP-based connections.</p>
<p>The cause is that the Fastify adapter for tRPC <a href="https://github.com/trpc/trpc/blob/7d10d7b028f1d85f6523e995ee7deb17dc886874/packages/server/src/adapters/fastify/fastifyTRPCPlugin.ts#L67">delegates to the non-Fastify-specific websocket adapter</a>. When that creates a context, the incoming <code>req</code> object is an instance of <code>IncomingMessage</code>, i.e. the underlying NodeJS request abstraction, which does <em>not</em> have the Fastify session details attached.</p>
<p>This probably should be better documented, ideally directly in the types (although that would probably be a fairly large breakage), or at least in the Fastify documentation.</p>
<p>The best solution I found is a <code>WeakMap</code> mapping <code>IncomingMessage</code> requests to <code>FastifyRequest</code> values, which have the expected <code>session</code> attribute. That looks something like this:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-typescript" data-lang="typescript"><span class="line"><span class="cl"><span class="c1">// create a new scope so that the hook we add later will only
</span></span></span><span class="line"><span class="cl"><span class="c1">// affect tRPC-specific requests
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="nx">app</span><span class="p">.</span><span class="nx">register</span><span class="p">((</span><span class="nx">app</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="c1">// use a WeakMap to avoid leaking memory by holding on to
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>  <span class="c1">// requests longer than necessary
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>  <span class="kr">const</span> <span class="nx">REQS</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">WeakMap</span><span class="o">&lt;</span>
</span></span><span class="line"><span class="cl">    <span class="nx">FastifyRequest</span> <span class="o">|</span> <span class="nx">IncomingMessage</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nx">FastifyRequest</span>
</span></span><span class="line"><span class="cl">  <span class="o">&gt;</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="nx">app</span><span class="p">.</span><span class="nx">addHook</span><span class="p">(</span><span class="s2">&#34;onRequest&#34;</span><span class="p">,</span> <span class="kr">async</span> <span class="p">(</span><span class="nx">req</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="c1">// associate each raw `IncomingMessage` (`req.raw`) with
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="c1">// the original `IncomingMessage`
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="nx">REQS</span><span class="p">.</span><span class="kr">set</span><span class="p">(</span><span class="nx">req</span><span class="p">.</span><span class="nx">raw</span><span class="p">,</span> <span class="nx">req</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">  <span class="p">});</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="nx">app</span><span class="p">.</span><span class="nx">register</span><span class="p">(</span><span class="nx">fastifyTRPCPlugin</span><span class="p">,</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nx">prefix</span><span class="o">:</span> <span class="s2">&#34;/trpc&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nx">useWSS</span>: <span class="kt">true</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nx">trpcOptions</span><span class="o">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="nx">router</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">      <span class="nx">onError</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">      <span class="nx">createContext</span><span class="o">:</span> <span class="p">({</span> <span class="nx">req</span> <span class="p">})</span> <span class="o">=&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="c1">// given either a `FastifyRequest` or an
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>        <span class="c1">// `IncomingMessage`, fetch the related
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>        <span class="c1">// `FastifyRequest` that we saved earlier
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>        <span class="kr">const</span> <span class="nx">realReq</span> <span class="o">=</span> <span class="nx">REQS</span><span class="p">.</span><span class="kr">get</span><span class="p">(</span><span class="nx">req</span><span class="p">.</span><span class="nx">raw</span> <span class="o">??</span> <span class="nx">req</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">realReq</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">          <span class="k">throw</span> <span class="k">new</span> <span class="nb">Error</span><span class="p">(</span><span class="s2">&#34;This should never happen&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">realReq</span><span class="p">.</span><span class="nx">session</span><span class="p">);</span> <span class="c1">// logs the session object
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>        <span class="k">return</span> <span class="p">{};</span>
</span></span><span class="line"><span class="cl">      <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl">  <span class="p">});</span>
</span></span><span class="line"><span class="cl"><span class="p">});</span>
</span></span></code></pre></div><p>Because the tRPC types aren&rsquo;t correct for the <code>req</code> parameter of the <code>createContext</code> callback, you might need to fiddle with the Typescript types to get this to work properly. Specifically, the <code>WeakMap</code> type here is technically incorrect, but means that I can do <code>REQS.get(req.raw ?? req)</code> without Typescript complaining. This does cause an ESLint error (because according to the type definitions, <code>req.raw</code> can never be null), but I&rsquo;d rather silence an ESLint error than a Typescript error.</p>
<p>I hope this helps you, or myself in six months&rsquo; time when I run into this issue again having forgotten about it completely.</p>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>Indeed, this is also what the types will tell you — if you are using Typescript, <code>req.session</code> will have the type of the Fastify session object in the example above.&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content:encoded></item><item><title>New Disposable APIs in Javascript</title><link>https://jonathan-frere.com/posts/disposables-in-javascript/</link><pubDate>Mon, 06 May 2024 00:00:00 +0000</pubDate><guid>https://jonathan-frere.com/posts/disposables-in-javascript/</guid><description>&lt;p>Javascript’s new &amp;ldquo;Explicit Resource Management&amp;rdquo; proposal adds the &lt;code>using&lt;/code> statement, a way to automatically close resources after you’ve finished using them. But as part of the same proposal, a number of other APIs have been added that make &lt;code>using&lt;/code> even more useful. I couldn’t find a lot of documentation out there when I was trying to figure out how these APIs work, so this article is a bit of an overview of getting started with &lt;code>using&lt;/code>, &lt;code>Disposable&lt;/code>s, and explicit resource management.&lt;/p></description><content:encoded><![CDATA[<p>Javascript’s new &ldquo;Explicit Resource Management&rdquo; proposal adds the <code>using</code> statement, a way to automatically close resources after you’ve finished using them. But as part of the same proposal, a number of other APIs have been added that make <code>using</code> even more useful. I couldn’t find a lot of documentation out there when I was trying to figure out how these APIs work, so this article is a bit of an overview of getting started with <code>using</code>, <code>Disposable</code>s, and explicit resource management.</p>
<h2 id="the-journey-to-using-using">
  <a href="#the-journey-to-using-using">The Journey to Using <code>using</code></a>
</h2>

<p>Many classes or objects represent some sort of resource, such as an open file or a database connection, that requires some cleanup logic when that resource is no longer in use. In NodeJS, the convention is typically to put this cleanup in a <code>close()</code> function. For example, the <code>Server</code> class in <code>node:http</code> has a <code>close()</code> method that stops new connections and closes existing ones.</p>
<p>The problem with <code>close</code> alone is that it’s easy not to call it. Sometimes it&rsquo;s a matter of forgetting, but often errors and exceptions can trip us up. Consider this function:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-tsx" data-lang="tsx"><span class="line"><span class="cl"><span class="kr">async</span> <span class="kd">function</span> <span class="nx">saveMessageInDatabase</span><span class="p">(</span><span class="nx">message</span>: <span class="kt">string</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="kr">const</span> <span class="nx">conn</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">DatabaseConnection</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">  <span class="kr">const</span> <span class="p">{</span> <span class="nx">sender</span><span class="p">,</span> <span class="nx">recipient</span><span class="p">,</span> <span class="nx">content</span> <span class="p">}</span> <span class="o">=</span> <span class="nx">parseMessage</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">  <span class="k">await</span> <span class="nx">conn</span><span class="p">.</span><span class="nx">insert</span><span class="p">({</span> <span class="nx">sender</span><span class="p">,</span> <span class="nx">recipient</span><span class="p">,</span> <span class="nx">content</span> <span class="p">});</span>
</span></span><span class="line"><span class="cl">  <span class="k">await</span> <span class="nx">conn</span><span class="p">.</span><span class="nx">close</span><span class="p">();</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>This creates a database connection at the start of the function, and closes it at the end. But we have a problem if <code>parseMessage</code> or <code>conn.insert(...)</code> throw an error — in this situation, the <code>saveMessageInDatabase</code> function will stop without closing the connection, leaving unclosed resources hanging around.</p>
<p>The first step to solving this is to formalise how a resource gets closed. We can do this using the <code>Disposable</code> interface or protocol:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-tsx" data-lang="tsx"><span class="line"><span class="cl"><span class="kr">interface</span> <span class="nx">Disposable</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="p">[</span><span class="nx">Symbol</span><span class="p">.</span><span class="nx">dispose</span><span class="p">]</span><span class="o">:</span> <span class="p">()</span> <span class="o">=&gt;</span> <span class="k">void</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>This is very similar to methods like <code>.close()</code>, <code>.cancel()</code>, and so on, but we use the <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol#well-known_symbols">well-known symbol</a> <code>Symbol.dispose</code> instead. This helps the runtime to distinguish between objects that have been intentionally made disposable (using this symbol), and objects that happen to have a certain name (e.g. <code>door.close()</code>).</p>
<p>With this in place, we can define the <code>using</code> syntax. <code>using</code> can be used in much the same way as <code>const</code>, and behaves very similarly in most respects.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-tsx" data-lang="tsx"><span class="line"><span class="cl"><span class="c1">// was: const varName = new MyDisposableObject();
</span></span></span><span class="line"><span class="cl"><span class="c1">// now:
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="nx">using</span> <span class="nx">varName</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">MyDisposableObject</span><span class="p">();</span>
</span></span><span class="line"><span class="cl"><span class="nx">varName</span><span class="p">.</span><span class="nx">method</span><span class="p">();</span>
</span></span></code></pre></div><p>However, <code>using</code> has a couple of restrictions in addition to the normal behaviour of <code>const</code>:</p>
<ul>
<li>With <code>using</code>, the variable <em>must</em> implement the <code>Disposable</code> protocol — i.e. it must have a <code>Symbol.dispose</code> method that can be called without arguments.</li>
<li>With <code>using</code>, you cannot destructure the variable you’re interested in (e.g. <code>using { field1, field2 } = disposable()</code>).</li>
</ul>
<p>When we leave the scope where a <code>using</code> variable was defined (i.e. when we return from the function in which <code>using</code> was used, or leave the if-block, or an exception gets thrown, etc), then the <code>Symbol.dispose</code> method will be called.</p>
<p>In addition, the dispose methods will be called in the reverse order to the way they were defined. So the object that was created first will be disposed of last. This reverse order is deliberate: we don’t want the database to be cleaned up while other resources are still using it!</p>
<p>An example:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-tsx" data-lang="tsx"><span class="line"><span class="cl"><span class="kd">function</span> <span class="nx">create</span><span class="p">(</span><span class="nx">data</span>: <span class="kt">string</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">	<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="sb">`creating disposable object with data </span><span class="si">${</span><span class="nx">data</span><span class="si">}</span><span class="sb">`</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">	<span class="k">return</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">		<span class="nx">data</span>: <span class="kt">data</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">		<span class="p">[</span><span class="nx">Symbol</span><span class="p">.</span><span class="nx">dispose</span><span class="p">]()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">			<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="sb">`disposing disposable object with data </span><span class="si">${</span><span class="nx">data</span><span class="si">}</span><span class="sb">`</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">		<span class="p">},</span>
</span></span><span class="line"><span class="cl">	<span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">function</span> <span class="nx">main() {</span>
</span></span><span class="line"><span class="cl">  <span class="nx">using</span> <span class="nx">data1</span> <span class="o">=</span> <span class="nx">create</span><span class="p">(</span><span class="s2">&#34;first&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">  <span class="nx">using</span> <span class="nx">data2</span> <span class="o">=</span> <span class="nx">create</span><span class="p">(</span><span class="s2">&#34;second&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="sb">`using </span><span class="si">${</span><span class="nx">data1</span><span class="p">.</span><span class="nx">data</span><span class="si">}</span><span class="sb"> and </span><span class="si">${</span><span class="nx">data2</span><span class="p">.</span><span class="nx">data</span><span class="si">}</span><span class="sb">`</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s2">&#34;before main&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="nx">main</span><span class="p">();</span>
</span></span><span class="line"><span class="cl"><span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s2">&#34;after main&#34;</span><span class="p">);</span>
</span></span></code></pre></div><p>This will produce the following logs:</p>
<pre tabindex="0"><code>before main
creating disposable object with data first
creating disposable object with data second
using first and second
disposing disposable object with data second
disposing disposable object with data first
after main
</code></pre><h2 id="async-disposables">
  <a href="#async-disposables">Async Disposables</a>
</h2>

<p>Often, when we want to dispose of a resource in Javascript, that cleanup/close/disposal operation will need to be asynchonous — for example due to waiting for connections to be cleaned up or data to be flushed.</p>
<p>So in addition to the standard <code>Disposable</code> protocol, there’s a second one, <code>AsyncDisposable</code>. This uses the <code>Symbol.asyncDispose</code> method, which returns a promise that should resolve when the resource is completely closed.</p>
<p>To use an async disposable, we have the <code>await using</code> syntax, which does the same thing as a normal <code>using</code> declaration, but, well, asynchronously. It must be called inside an <code>async</code> function (i.e. it needs to be called in a place where normal <code>await</code> is allowed).</p>
<p>The <code>await using</code> syntax can also handle non-async <code>Disposable</code> objects, which means if you don’t know whether a given resource is going to be asynchronously or synchronously disposed, you can use <code>await using</code> and cover both options.</p>
<table>
  <thead>
      <tr>
          <th style="text-align: right"></th>
          <th style="text-align: left"><code>await using</code></th>
          <th style="text-align: left"><code>using</code></th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td style="text-align: right"><strong>Usable In:</strong></td>
          <td style="text-align: left">async functions only</td>
          <td style="text-align: left">async and sync functions</td>
      </tr>
      <tr>
          <td style="text-align: right"><strong>Protocol:</strong></td>
          <td style="text-align: left"><code>AsyncDisposable</code> + <code>Disposable</code></td>
          <td style="text-align: left">only <code>Disposable</code></td>
      </tr>
      <tr>
          <td style="text-align: right"><strong>Symbol:</strong></td>
          <td style="text-align: left"><code>Symbol.asyncDispose</code>/<code>Symbol.dispose</code></td>
          <td style="text-align: left"><code>Symbol.dispose</code></td>
      </tr>
  </tbody>
</table>
<h2 id="collections-of-disposables">
  <a href="#collections-of-disposables">Collections of Disposables</a>
</h2>

<p>Sometimes it&rsquo;s not enough to use function scope to handle resources. We might have a class or object that owns and manages a number of different resources. It would be useful if we could group all of its resources together in a similar way to <code>using</code>, but as a class variable or as part of a closure.</p>
<p>One convenient way of doing this is using the <code>DisposableStack</code> and <code>AsyncDisposableStack</code> classes. These represent stacks of resources managed by the <code>DisposableStack</code> or <code>AsyncDisposableStack</code> object — if we clean up the stack, all the resources that it manages will also get cleaned up. They can be created using the <code>new</code> operator, and provide three different methods for adding resources to the stack:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-typescript" data-lang="typescript"><span class="line"><span class="cl"><span class="kr">const</span> <span class="nx">stack</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">DisposableStack</span><span class="p">();</span> <span class="c1">// or ` = new AsyncDisposableStack()`
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>
</span></span><span class="line"><span class="cl"><span class="c1">// .use() takes a resource, adds it to the resources managed by the stack,
</span></span></span><span class="line"><span class="cl"><span class="c1">// and returns the resource so it can be used elsewhere.
</span></span></span><span class="line"><span class="cl"><span class="c1">// The resource must be a disposable item using the `Symbol.dispose` method
</span></span></span><span class="line"><span class="cl"><span class="c1">// (or `Symbol.asyncDispose` if using `AsyncDisposableStack`).
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kr">const</span> <span class="nx">resource1</span> <span class="o">=</span> <span class="nx">stack</span><span class="p">.</span><span class="nx">use</span><span class="p">(</span><span class="k">new</span> <span class="nx">MyResource</span><span class="p">());</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// `.defer()` schedules a callback to take place when the stack gets disposed.
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kr">const</span> <span class="nx">handle</span> <span class="o">=</span> <span class="nx">setInterval</span><span class="p">(()</span> <span class="o">=&gt;</span> <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s2">&#34;running&#34;</span><span class="p">),</span> <span class="mi">5000</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="nx">stack</span><span class="p">.</span><span class="nx">defer</span><span class="p">(()</span> <span class="o">=&gt;</span> <span class="nx">clearInterval</span><span class="p">(</span><span class="nx">handle</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// .adopt() combines the above two behaviours: it takes a resource and a
</span></span></span><span class="line"><span class="cl"><span class="c1">// disposal callback, and calls the callback with the resource as its argument
</span></span></span><span class="line"><span class="cl"><span class="c1">// when the stack gets disposed.  The resource does _not_ need to implement
</span></span></span><span class="line"><span class="cl"><span class="c1">// the disposable protocol.
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kr">const</span> <span class="nx">resource2</span> <span class="o">=</span> <span class="nx">stack</span><span class="p">.</span><span class="nx">adopt</span><span class="p">(</span><span class="k">new</span> <span class="nx">OtherResource</span><span class="p">(),</span> <span class="p">(</span><span class="nx">r</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="nx">r</span><span class="p">.</span><span class="nx">close</span><span class="p">());</span>
</span></span></code></pre></div><p>Stacks are themselves disposable, so can be disposed of using the <code>Symbol.dispose</code> or <code>Symbol.asyncDispose</code> methods. For convenience, this method is also exposed simple as <code>.dispose()</code> or <code>.asyncDispose()</code>. As mentioned earlier, this method (either using <code>Symbol.dispose</code>/<code>Symbol.asyncDispose</code> or via the alias method) will dispose of all of the resources managed by this stack. Similarly to the <code>using</code> declaration, the resources will be cleaned up in reverse order to prevent issues where resources depend on each other.</p>
<table>
  <thead>
      <tr>
          <th style="text-align: right"></th>
          <th style="text-align: left"><code>AsyncDisposableStack</code></th>
          <th style="text-align: left"><code>DisposableStack</code></th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td style="text-align: right"><strong>Implements:</strong></td>
          <td style="text-align: left"><code>AsyncDisposable</code></td>
          <td style="text-align: left"><code>Disposable</code></td>
      </tr>
      <tr>
          <td style="text-align: right"><strong>Manages:</strong></td>
          <td style="text-align: left"><code>AsyncDisposable</code> + <code>Disposable</code></td>
          <td style="text-align: left">only <code>Disposable</code></td>
      </tr>
      <tr>
          <td style="text-align: right"><strong>Dispose With:</strong></td>
          <td style="text-align: left"><code>.disposeAsync()</code></td>
          <td style="text-align: left"><code>.dispose()</code></td>
      </tr>
  </tbody>
</table>
<h2 id="useful-patterns-with-explicit-resource-management">
  <a href="#useful-patterns-with-explicit-resource-management">Useful Patterns with Explicit Resource Management</a>
</h2>

<p>Hopefully by now it should be clear what disposable resources are, how they can be manipulated, etc. But it still took me a while to get my head around some typical patterns with disposables, how they can be manipulated, and some best practices. So here are a few short sections which explain a couple of ideas that are now possible, and the best ways to achieve some common goals.</p>
<h3 id="anonymous-defers">
  <a href="#anonymous-defers">Anonymous Defers</a>
</h3>

<p>If you’re coming from other languages with features similar to using, such as Go with its <code>defer</code> statement, then you may be surprised that <code>using</code> is really a variable declaration — it’s basically the same as <code>const</code> or <code>let</code>, but it also automatically cleans up resources when the function has completed.</p>
<p>As a result, every time you use <code>using</code>, you need to declare a variable name. But often you don’t want to specify a variable name — e.g. if you want to defer a callback until the end of the function. It’s possible to do something like <code>using _ = ...</code>, using _ as a kind of informal placeholder, but this only works once per function body.</p>
<p>The best solution I’ve found is <code>DisposableStack</code> (or <code>AsyncDisposableStack</code>) and the <code>defer</code> method:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-tsx" data-lang="tsx"><span class="line"><span class="cl"><span class="kd">function</span> <span class="nx">main() {</span>
</span></span><span class="line"><span class="cl">	<span class="nx">using</span> <span class="nx">stack</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">DisposableStack</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">	<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s2">&#34;starting function&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">	<span class="nx">stack</span><span class="p">.</span><span class="nx">defer</span><span class="p">(()</span> <span class="o">=&gt;</span> <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s2">&#34;ending function&#34;</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">	<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s2">&#34;during function body&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><h3 id="disposable-timeouts-and-intervals">
  <a href="#disposable-timeouts-and-intervals">Disposable Timeouts and Intervals</a>
</h3>

<p>The specification gives a list of various browser and JS APIs that will be retrofitted with the disposable mechanism, but one API that is noticeably missing is the <code>setInterval</code> and <code>setTimeout</code> functions. Currently, they can be cancelled using the <code>clearInterval</code> and <code>clearTimeout</code> functions, and we can use <code>defer</code> to integrate them into a disposable stack:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-tsx" data-lang="tsx"><span class="line"><span class="cl"><span class="kd">function</span> <span class="nx">main() {</span>
</span></span><span class="line"><span class="cl">	<span class="nx">using</span> <span class="nx">stack</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">DisposableStack</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">	<span class="kr">const</span> <span class="nx">handle</span> <span class="o">=</span> <span class="nx">setInterval</span><span class="p">(()</span> <span class="o">=&gt;</span> <span class="p">{</span><span class="cm">/* ... */</span><span class="p">},</span> <span class="mi">5000</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">	<span class="nx">stack</span><span class="p">.</span><span class="nx">defer</span><span class="p">(()</span> <span class="o">=&gt;</span> <span class="nx">clearInterval</span><span class="p">(</span><span class="nx">handle</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">	<span class="c1">// ...
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">}</span>
</span></span></code></pre></div><p>In fact, if you’re using NodeJS, you can go one better. The NodeJS timers (i.e. <code>setInterval</code> and friends) already return an object (<a href="https://nodejs.org/api/timers.html#class-timeout"><code>Timeout</code></a>) with lots of useful functions like <code>.unref()</code>. Recent versions of v18 and upwards now also include a <code>Symbol.dispose</code> key for these objects, which means you can simplify the above code to this:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-tsx" data-lang="tsx"><span class="line"><span class="cl"><span class="kd">function</span> <span class="nx">main() {</span>
</span></span><span class="line"><span class="cl">	<span class="nx">using</span> <span class="nx">setInterval</span><span class="p">(()</span> <span class="o">=&gt;</span> <span class="p">{</span><span class="cm">/* ... */</span><span class="p">},</span> <span class="mi">5000</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">	<span class="c1">// ...
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">}</span>
</span></span></code></pre></div><p>And in the browser, we can write a similar utility function:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-tsx" data-lang="tsx"><span class="line"><span class="cl"><span class="kr">export</span> <span class="kd">function</span> <span class="nx">interval</span><span class="p">(...</span><span class="nx">args</span>: <span class="kt">Parameters</span><span class="p">&lt;</span><span class="nt">typeof</span> <span class="na">setInterval</span><span class="p">&gt;)</span><span class="o">:</span> <span class="nx">Disposable</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="kr">const</span> <span class="nx">handle</span> <span class="o">=</span> <span class="nx">setInterval</span><span class="p">(...</span><span class="nx">args</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">  <span class="k">return</span> <span class="p">{</span> <span class="p">[</span><span class="nx">Symbol</span><span class="p">.</span><span class="nx">dispose</span><span class="p">]</span><span class="o">:</span> <span class="p">()</span> <span class="o">=&gt;</span> <span class="nx">clearInterval</span><span class="p">(</span><span class="nx">handle</span><span class="p">)</span> <span class="p">};</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><h3 id="the-use-and-move-maneuver">
  <a href="#the-use-and-move-maneuver">The Use-and-Move Maneuver</a>
</h3>

<p>One more subtle but incredibly powerful method in the <code>DisposableStack</code> arsenal is <code>.move()</code>. This creates a new stack, moves all of the resources in the current stack into the new stack, and then marks the original stack as disposed. None of the resources will be disposed except for the original stack.</p>
<p>This is a powerful tool for anywhere where you’re creating resources for use elsewhere (so you want to put them in a stack), but the very act of creating resources is something that might fail (so you want to be <code>using</code> that stack when you create them.</p>
<p>Consider this example, which can cause resource leakages:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-tsx" data-lang="tsx"><span class="line"><span class="cl"><span class="kr">export</span> <span class="kd">function</span> <span class="nx">badOpenFiles</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">  <span class="nx">fileList</span>: <span class="kt">string</span><span class="p">[]</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span><span class="o">:</span> <span class="p">{</span> <span class="nx">files</span>: <span class="kt">File</span><span class="p">[]</span> <span class="p">}</span> <span class="o">&amp;</span> <span class="nx">Disposable</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="kr">const</span> <span class="nx">stack</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">DisposableStack</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">  <span class="kr">const</span> <span class="nx">files</span> <span class="o">=</span> <span class="p">[];</span>
</span></span><span class="line"><span class="cl">  <span class="k">for</span> <span class="p">(</span><span class="kr">const</span> <span class="nx">fileName</span> <span class="k">of</span> <span class="nx">fileList</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nx">files</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">stack</span><span class="p">.</span><span class="nx">use</span><span class="p">(</span><span class="nx">open</span><span class="p">(</span><span class="nx">fileName</span><span class="p">)));</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="k">return</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nx">files</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="p">[</span><span class="nx">Symbol</span><span class="p">.</span><span class="nx">dispose</span><span class="p">]</span><span class="o">:</span> <span class="p">()</span> <span class="o">=&gt;</span> <span class="nx">stack</span><span class="p">.</span><span class="nx">dispose</span><span class="p">(),</span>
</span></span><span class="line"><span class="cl">  <span class="p">};</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>If I call this with a list of files, it’ll open all of those files and return them as single disposable object, that when it gets disposed of, closes all the files again.</p>
<p>But let’s say I call this with the file list <code>[&quot;file1.txt&quot;, &quot;file2.txt&quot;, &quot;file-does-not-exist.txt&quot;, &quot;file4.txt&quot;]</code>. Now, the first two files get created and added to the stack, but the third one causes an error, which exists the function. But because the stack was never added to a <code>using</code> declaration anywhere, those files will never be closed, which causes resource leakage.</p>
<p>The <code>.move()</code> function allows us to do this instead:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-tsx" data-lang="tsx"><span class="line"><span class="cl"><span class="kr">export</span> <span class="kd">function</span> <span class="nx">openFiles</span><span class="p">(</span><span class="nx">fileList</span>: <span class="kt">string</span><span class="p">[])</span><span class="o">:</span> <span class="p">{</span> <span class="nx">files</span>: <span class="kt">File</span><span class="p">[]</span> <span class="p">}</span> <span class="o">&amp;</span> <span class="nx">Disposable</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="c1">// Note we use the stack here, which means this stack will be cleaned up
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>  <span class="c1">// when we return from the function.
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>	<span class="nx">using</span> <span class="nx">stack</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">DisposableStack</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">	<span class="kr">const</span> <span class="nx">files</span> <span class="o">=</span> <span class="p">[];</span>
</span></span><span class="line"><span class="cl">	<span class="k">for</span> <span class="p">(</span><span class="kr">const</span> <span class="nx">fileName</span> <span class="k">of</span> <span class="nx">fileList</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">		<span class="nx">files</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">stack</span><span class="p">.</span><span class="nx">use</span><span class="p">(</span><span class="nx">open</span><span class="p">(</span><span class="nx">fileName</span><span class="p">)));</span>
</span></span><span class="line"><span class="cl">	<span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">	<span class="c1">// We&#39;ve successfully created all the files with no errors.
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>	<span class="c1">// Move the opened file resources out of the stack, and into a new
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>	<span class="c1">// one that won&#39;t get closed at the end of this function.
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>	<span class="kr">const</span> <span class="nx">closer</span> <span class="o">=</span> <span class="nx">stack</span><span class="p">.</span><span class="nx">move</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">	<span class="k">return</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">		<span class="nx">files</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">		<span class="p">[</span><span class="nx">Symbol</span><span class="p">.</span><span class="nx">dispose</span><span class="p">]</span><span class="o">:</span> <span class="p">()</span> <span class="o">=&gt;</span> <span class="nx">closer</span><span class="p">.</span><span class="nx">dispose</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">	<span class="p">};</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><h3 id="the-disposable-wrapper">
  <a href="#the-disposable-wrapper">The Disposable Wrapper</a>
</h3>

<p>Right now, <code>Disposable</code>s are still relatively new, and so it&rsquo;s not unlikely that the library you&rsquo;re working with doesn&rsquo;t support them, opting instead for a <code>.close()</code> method or something similar. But Javascript is a dynamic language, so it&rsquo;s not too hard to get these tools to behave. Here&rsquo;s an example for MongoDB, which at the time of writing does not support <code>using</code> or any of the disposable protocols:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-typescript" data-lang="typescript"><span class="line"><span class="cl"><span class="kd">function</span> <span class="nx">createMongoClient</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">  <span class="nx">connection</span>: <span class="kt">string</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="nx">options?</span>: <span class="kt">MongoClientOptions</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span><span class="o">:</span> <span class="nx">MongoClient</span> <span class="o">&amp;</span> <span class="nx">Disposable</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="kr">const</span> <span class="nx">client</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">MongoClient</span><span class="p">(</span><span class="nx">connection</span><span class="p">,</span> <span class="nx">options</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="k">if</span> <span class="p">(</span><span class="nx">client</span><span class="p">[</span><span class="nx">Symbol</span><span class="p">.</span><span class="nx">asyncDispose</span><span class="p">])</span> <span class="k">throw</span> <span class="k">new</span> <span class="nb">Error</span><span class="p">(</span><span class="s2">&#34;this code is unnecessary&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">  <span class="k">return</span> <span class="nb">Object</span><span class="p">.</span><span class="nx">assign</span><span class="p">(</span><span class="nx">client</span><span class="p">,</span> <span class="p">{</span> <span class="p">[</span><span class="nx">Symbol</span><span class="p">.</span><span class="nx">asyncDispose</span><span class="p">]</span><span class="o">:</span> <span class="p">()</span> <span class="o">=&gt;</span> <span class="nx">client</span><span class="p">.</span><span class="nx">close</span><span class="p">()</span> <span class="p">});</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>This will add a <code>Symbol.asyncDispose</code> method to the client, meaning you can use it in <code>await using</code> declarations and with <code>AsyncDisposableStack#use()</code>. In addition, if you ever update to a version of MongoDB that does implement the <code>AsyncDisposable</code> protocol, you&rsquo;ll get an error reminding you to delete the code.</p>
<h3 id="awaiting-signals">
  <a href="#awaiting-signals">Awaiting Signals</a>
</h3>

<p>A common pattern for NodeJS servers is to start up the web server, and then add event handlers for the OS&rsquo;s &ldquo;quit&rdquo; signals (e.g. <code>SIGINT</code>). Inside these handlers, we can shut the server down, clean up resources, etc.</p>
<p>This works fine, but the control flow can be difficult to follow, and we have to manually call the <code>Symbol.dispose</code> and <code>Symbol.asyncDispose</code> methods where that&rsquo;s relevant. It would be nice if there was a way to tie the lifetime of the application to the lifetime of a single function, so that when that function exits, the server will also automatically exit, closing and disposing of all resources along the way.</p>
<p>Enter NodeJS&rsquo;s <code>once</code> function, which converts an event into a promise<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-typescript" data-lang="typescript"><span class="line"><span class="cl"><span class="kr">import</span> <span class="p">{</span> <span class="nx">once</span> <span class="p">}</span> <span class="kr">from</span> <span class="s2">&#34;node:events&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// waits until the `SIGINT` signal has been triggered, e.g. from Ctrl-C
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">await</span> <span class="nx">once</span><span class="p">(</span><span class="nx">process</span><span class="p">,</span> <span class="s2">&#34;SIGINT&#34;</span><span class="p">);</span>
</span></span></code></pre></div><p>Using this, we can write a <code>main()</code> function that lives for the entire length of the application, and quits when the application is stopped, automatically cleaning up any resources after itself:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-typescript" data-lang="typescript"><span class="line"><span class="cl"><span class="kr">async</span> <span class="kd">function</span> <span class="nx">main() {</span>
</span></span><span class="line"><span class="cl">  <span class="k">await</span> <span class="nx">using</span> <span class="nx">stack</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">AsyncDisposableStack</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">  <span class="k">await</span> <span class="nx">using</span> <span class="nx">resource</span> <span class="o">=</span> <span class="nx">createResource</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">  <span class="c1">// ... etc, for as many resources as make sense
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>
</span></span><span class="line"><span class="cl">  <span class="c1">// alternatively, use the &#34;Disposable Wrapper&#34; pattern from earlier
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>  <span class="kr">const</span> <span class="nx">server</span> <span class="o">=</span> <span class="nx">stack</span><span class="p">.</span><span class="nx">adopt</span><span class="p">(</span><span class="nx">express</span><span class="p">(),</span> <span class="nx">server</span> <span class="o">=&gt;</span> <span class="nx">server</span><span class="p">.</span><span class="nx">close</span><span class="p">());</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="c1">// add routes, use resources, etc
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>  <span class="nx">server</span><span class="p">.</span><span class="kr">get</span><span class="p">(</span><span class="cm">/* ... */</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="nx">logger</span><span class="p">.</span><span class="nx">info</span><span class="p">(</span><span class="s2">&#34;starting application on port 5000&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">  <span class="nx">server</span><span class="p">.</span><span class="nx">listen</span><span class="p">(</span><span class="mi">5000</span><span class="p">,</span> <span class="p">()</span> <span class="o">=&gt;</span> <span class="nx">logger</span><span class="p">.</span><span class="nx">info</span><span class="p">(</span><span class="s2">&#34;application started&#34;</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="k">await</span> <span class="nx">Promise</span><span class="p">.</span><span class="nx">race</span><span class="p">([</span>
</span></span><span class="line"><span class="cl">    <span class="nx">once</span><span class="p">(</span><span class="nx">process</span><span class="p">,</span> <span class="s2">&#34;SIGINT&#34;</span><span class="p">),</span> <span class="c1">// Ctrl-C
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="nx">once</span><span class="p">(</span><span class="nx">process</span><span class="p">,</span> <span class="s2">&#34;SIGTERM&#34;</span><span class="p">),</span> <span class="c1">// OS/k8s/etc requested termination
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="c1">// etc.
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>  <span class="p">]);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="nx">logger</span><span class="p">.</span><span class="nx">info</span><span class="p">(</span><span class="s2">&#34;shutting down application&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>Because all of our resources are managed either by <code>using</code> directly, or by the <code>stack</code> which is in turn tied to the application&rsquo;s lifespan, we don&rsquo;t need to manually close anything after the signals have been handled — everything will automatically be gracefully shutdown.</p>
<h2 id="using-explicit-resource-management-today">
  <a href="#using-explicit-resource-management-today">Using Explicit Resource Management Today</a>
</h2>

<p>Right now, explicit resource management is a stage three proposal — that means that the specification has been completed and approved, and browsers and other tools are encouraged to start implementing the proposal, and trying the feature out in practice<sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup>.</p>
<p>This means that if you want to try this feature out right now, you&rsquo;re going to need to transpile the syntax to a format supported by older browsers, and provide a polyfill for the various global objects that the feature requires.</p>
<p>In terms of transpiling, both Typescript and Babel support the <code>using ...</code> syntax. For Typescript, you&rsquo;ll need <a href="https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-2.html#using-declarations-and-explicit-resource-management">version 5.2 or greater</a> to handle the syntax. In the <code>tsconfig.json</code> file, the <code>target</code> should be <code>ES2022</code> or lower in order to do the transpilation (otherwise Typescript will leave the syntax unchanged), and the <code>lib</code> setting should include <code>esnext.disposable</code> (or alternatively the whole <code>esnext</code> bundle of types) to ensure that the right set of types is included. For Babel, including the <code>stage-3</code> preset, or explicitly adding the <a href="https://babeljs.io/docs/babel-plugin-proposal-explicit-resource-management"><code>@babel/plugin-proposal-explicit-resource-management</code> plugin</a> should ensure that everything gets compiled correctly.</p>
<p>Neither Typescript nor Babel include a polyfill for the various global types discussed here, which means you&rsquo;ll also need a polyfill. For this, there are various options, including <a href="https://www.npmjs.com/package/disposablestack">disposablestack</a>, which I&rsquo;ve been using, and CoreJS.</p>
<h2 id="bringing-it-all-together">
  <a href="#bringing-it-all-together">Bringing It All Together</a>
</h2>

<p>Let’s say we’re writing something on the backend, and there’s a lot of interactions with users. We want a class that handles all of our user-based logic:</p>
<ul>
<li>It can create/read/update/delete our user objects in the database</li>
<li>It automatically deletes users that haven’t been active in the last five minutes (we’re <em>very</em> GDPR conscious here, we don’t keep data a second longer than we need to)</li>
<li>It provides a stream of all the new users inserted into the database, so that elsewhere we can send them a lovely greeting message.</li>
</ul>
<p>We’ll use dependency injection so that we don’t need to create the database connection ourselves, but some of the resources will be managed by the user service. We can use the <code>AsyncDisposableStack</code> to group those resources together, and we&rsquo;ll add a <code>Symbol.asyncDispose</code> method that delegates to the stack&rsquo;s dispose method to handle that disposal. We can even implement Typescript&rsquo;s <code>AsyncDisposable</code> interface to make sure that we get everything right:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-tsx" data-lang="tsx"><span class="line"><span class="cl"><span class="kr">export</span> <span class="kr">class</span> <span class="nx">UserService</span> <span class="kr">implements</span> <span class="nx">AsyncDisposable</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="err">#</span><span class="nx">conn</span>: <span class="kt">DB.Conn</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="err">#</span><span class="nx">stack</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">AsyncDisposableStack</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">  <span class="err">#</span><span class="nx">intervalHandle</span>: <span class="kt">NodeJS.Timeout</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="err">#</span><span class="nx">streamHandle</span>: <span class="kt">DB.StreamHandle</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="kr">constructor</span><span class="p">(</span><span class="nx">conn</span>: <span class="kt">DB.Conn</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="c1">// Our DB connection, passed in via dependency injection -- so we don&#39;t want
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="c1">// to add this to the set of resources managed by this service!
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="k">this</span><span class="p">.</span><span class="err">#</span><span class="nx">conn</span> <span class="o">=</span> <span class="nx">conn</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1">// Remember, NodeJS&#39;s `Timeout` class already has a `Symbol.dispose` method,
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="c1">// so we can add that to the stack
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="k">this</span><span class="p">.</span><span class="err">#</span><span class="nx">timeoutHandle</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="err">#</span><span class="nx">stack</span><span class="p">.</span><span class="nx">use</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">      <span class="nx">setInterval</span><span class="p">(()</span> <span class="o">=&gt;</span> <span class="k">this</span><span class="p">.</span><span class="nx">deleteInactiveUsers</span><span class="p">(),</span> <span class="mi">60</span> <span class="o">*</span> <span class="mi">1000</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1">// For resources that don&#39;t have the right methods, `.adopt()` is the
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="c1">// easiest way to add an &#34;on dispose&#34; cleanup function
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="k">this</span><span class="p">.</span><span class="err">#</span><span class="nx">streamHandle</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="err">#</span><span class="nx">stack</span><span class="p">.</span><span class="nx">adopt</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">      <span class="k">this</span><span class="p">.</span><span class="err">#</span><span class="nx">createNewUserStream</span><span class="p">(),</span>
</span></span><span class="line"><span class="cl">      <span class="c1">// Closing this stream is an async operation, hence why we&#39;re using
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>      <span class="c1">// Symbol.asyncDispose, AsyncDisposableStack, etc.
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>      <span class="kr">async</span> <span class="p">(</span><span class="nx">stream</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="k">await</span> <span class="nx">stream</span><span class="p">.</span><span class="nx">close</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">    <span class="p">);</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="kr">async</span> <span class="p">[</span><span class="nx">Symbol</span><span class="p">.</span><span class="nx">asyncDispose</span><span class="p">]()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">await</span> <span class="k">this</span><span class="p">.</span><span class="err">#</span><span class="nx">stack</span><span class="p">.</span><span class="nx">dispose</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="c1">// ... methods and implementation details
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">}</span>
</span></span></code></pre></div><p>Now we need to actually construct all of our resources somewhere. We can add a <code>createResources</code> function that creates the resources, returns a disposable object that cleans up all of the resources together, and also ensures that if an error occurs during resource construction, everything will still get cleaned up gracefully — this is the power of the stack!</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-tsx" data-lang="tsx"><span class="line"><span class="cl"><span class="kr">export</span> <span class="kr">async</span> <span class="kd">function</span> <span class="nx">createResources</span><span class="p">(</span><span class="nx">config</span>: <span class="kt">Config</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="k">await</span> <span class="nx">using</span> <span class="nx">stack</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">AsyncDisposableStack</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">  <span class="kr">const</span> <span class="nx">db</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">MyDbDriver</span><span class="p">(</span><span class="nx">config</span><span class="p">.</span><span class="nx">connectionString</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">  <span class="kr">const</span> <span class="nx">conn</span> <span class="o">=</span> <span class="nx">stack</span><span class="p">.</span><span class="nx">use</span><span class="p">(</span><span class="k">await</span> <span class="nx">db</span><span class="p">.</span><span class="nx">connect</span><span class="p">());</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="c1">// When the stack disposes of its resources, the `UserService` will be cleaned
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>  <span class="c1">// up before the `conn`, which prevents errors where the `UserService` is
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>  <span class="c1">// trying to use a connection that doesn&#39;t exist anymore.
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>  <span class="kr">const</span> <span class="nx">userService</span> <span class="o">=</span> <span class="nx">stack</span><span class="p">.</span><span class="nx">use</span><span class="p">(</span><span class="k">new</span> <span class="nx">UserService</span><span class="p">(</span><span class="nx">conn</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="c1">// Now all the resources have been set up, use .move() to create a new stack
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>  <span class="c1">// and return a dispose method based on the new stack.
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>  <span class="kr">const</span> <span class="nx">closer</span> <span class="o">=</span> <span class="nx">stack</span><span class="p">.</span><span class="nx">move</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">  <span class="k">return</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nx">userService</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="p">[</span><span class="nx">Symbol</span><span class="p">.</span><span class="nx">asyncDispose</span><span class="p">]</span><span class="o">:</span> <span class="kr">async</span> <span class="p">()</span> <span class="o">=&gt;</span> <span class="k">await</span> <span class="nx">closer</span><span class="p">.</span><span class="nx">dispose</span><span class="p">(),</span>
</span></span><span class="line"><span class="cl">  <span class="p">};</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>Now finally, we need to plug all of this into our server implementation, and make sure that everything gets cleaned up when the server gracefully exits. We can use signals and promises to catch the events that should trigger a shutdown, and use the <code>using</code> declarations to automatically clean up any resources.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-typescript" data-lang="typescript"><span class="line"><span class="cl"><span class="kr">async</span> <span class="kd">function</span> <span class="nx">main() {</span>
</span></span><span class="line"><span class="cl">  <span class="kr">const</span> <span class="nx">config</span> <span class="o">=</span> <span class="k">await</span> <span class="nx">loadConfig</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">  <span class="nx">using</span> <span class="nx">resources</span> <span class="o">=</span> <span class="nx">createResources</span><span class="p">(</span><span class="nx">config</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">  <span class="nx">using</span> <span class="nx">stack</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">AsyncDisposableStack</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="c1">// create wrapper functions around APIs that don&#39;t yet support disposables
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>  <span class="nx">using</span> <span class="nx">server</span> <span class="o">=</span> <span class="nx">createFastify</span><span class="p">({});</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="nx">server</span><span class="p">.</span><span class="kr">get</span><span class="p">(</span><span class="cm">/* route using resources.userService */</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="k">await</span> <span class="nx">server</span><span class="p">.</span><span class="nx">listen</span><span class="p">({</span> <span class="nx">port</span>: <span class="kt">3000</span> <span class="p">})</span>
</span></span><span class="line"><span class="cl">  <span class="nx">logger</span><span class="p">.</span><span class="nx">info</span><span class="p">(</span><span class="s2">&#34;server running on port 3000&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="c1">// use `once` to turn one-time events into promises
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>  <span class="k">await</span> <span class="nx">Promise</span><span class="p">.</span><span class="nx">race</span><span class="p">([</span>
</span></span><span class="line"><span class="cl">    <span class="nx">once</span><span class="p">(</span><span class="nx">process</span><span class="p">,</span> <span class="s2">&#34;SIGINT&#34;</span><span class="p">),</span>
</span></span><span class="line"><span class="cl">    <span class="nx">once</span><span class="p">(</span><span class="nx">process</span><span class="p">,</span> <span class="s2">&#34;SIGTERM&#34;</span><span class="p">),</span>
</span></span><span class="line"><span class="cl">    <span class="nx">once</span><span class="p">(</span><span class="nx">process</span><span class="p">,</span> <span class="s2">&#34;SIGHUP&#34;</span><span class="p">),</span>
</span></span><span class="line"><span class="cl">  <span class="p">]);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="nx">logger</span><span class="p">.</span><span class="nx">info</span><span class="p">(</span><span class="s2">&#34;server terminated, closing down&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="c1">// resources will all be cleaned up here
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">}</span>
</span></span></code></pre></div><h2 id="more-resources">
  <a href="#more-resources">More Resources</a>
</h2>

<p>There&rsquo;s a lot more information out there about the explicit resource management proposal, but given how Google isn&rsquo;t working as well as it once was, here are some links to help you find it:</p>
<ul>
<li><a href="https://github.com/tc39/proposal-explicit-resource-management">The original proposal</a> in the TC39 GitHub organisation. The documentation is a bit technically-focussed here, but the issues provide a lot of good context for the APIs, and a number of examples that explain why certain decisions were made.</li>
<li><a href="https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-2.html">Typescript 5.2&rsquo;s release notes</a> include a section about resource management, how to use it, and how to get it working in Typescript.</li>
<li>Various tickets/bugs/issues about implementing explicit resource management:
<ul>
<li><a href="https://issues.chromium.org/issues/42203506">Chrome</a></li>
<li><a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1569081">Firefox</a></li>
<li><a href="https://bugs.webkit.org/show_bug.cgi?id=248707">Safari</a></li>
</ul>
</li>
<li>Prior art in other languages:
<ul>
<li><a href="https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/statements/using">C#&rsquo;s <code>using</code> statement</a> is a big influence here.</li>
<li><a href="https://gobyexample.com/defer">Go&rsquo;s <code>defer</code> statement</a> inspired the <code>.defer</code> method.</li>
<li><a href="https://docs.python.org/3/library/contextlib.html#contextlib.ExitStack">Python&rsquo;s <code>ExitStack</code></a> is an explicit inspiration for the <code>DisposableStack</code> and <code>AsyncDisposableStack</code> classes.</li>
</ul>
</li>
</ul>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>Note that if you don&rsquo;t have access to NodeJS, you can replicate this functionality using <code>new Promise(...)</code> manually, although this can be tricky to do properly as it&rsquo;s difficult to ensure that resources get correctly cleaned up once an event has been triggered.&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:2">
<p>For the people who like that sort of thing, you can see the tickets where this is being implemented for <a href="https://issues.chromium.org/issues/42203506">Chrome</a>, <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1569081">Firefox</a>, and <a href="https://bugs.webkit.org/show_bug.cgi?id=248707">Safari</a>.&#160;<a href="#fnref:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content:encoded></item><item><title>How I Do Dependency Injection With Closures</title><link>https://jonathan-frere.com/posts/how-i-do-dependency-injection-with-closures/</link><pubDate>Tue, 31 Oct 2023 00:00:00 +0000</pubDate><guid>https://jonathan-frere.com/posts/how-i-do-dependency-injection-with-closures/</guid><description>&lt;blockquote>
&lt;p>You can also find an edited and updated version of this post that I wrote for my employer&amp;rsquo;s blog &lt;a href="https://www.esveo.com/en/blog/dependency-injection-with-closures/">here&lt;/a>.&lt;/p>
&lt;/blockquote>
&lt;p>A &lt;a href="https://www.reddit.com/r/Python/comments/17k9oai/autowired_my_minimalistic_approach_to_dependency/k77cv83/?context=10000">discussion&lt;/a> came up on Reddit recently about DI, where I mentioned that one way that I&amp;rsquo;ve done DI recently for web frameworks that don&amp;rsquo;t naturally support it to using closures. Someone asked for an example, so I figured I&amp;rsquo;d explain what that looks like and where it might work (or not work). The original question was about Python, but I&amp;rsquo;ll give Python and Javascript examples.&lt;/p></description><content:encoded><![CDATA[<blockquote>
<p>You can also find an edited and updated version of this post that I wrote for my employer&rsquo;s blog <a href="https://www.esveo.com/en/blog/dependency-injection-with-closures/">here</a>.</p>
</blockquote>
<p>A <a href="https://www.reddit.com/r/Python/comments/17k9oai/autowired_my_minimalistic_approach_to_dependency/k77cv83/?context=10000">discussion</a> came up on Reddit recently about DI, where I mentioned that one way that I&rsquo;ve done DI recently for web frameworks that don&rsquo;t naturally support it to using closures. Someone asked for an example, so I figured I&rsquo;d explain what that looks like and where it might work (or not work). The original question was about Python, but I&rsquo;ll give Python and Javascript examples.</p>
<p>I&rsquo;m going to start with some context of my dependency injection philosophy, but if you want to skip that, you can jump straight to some examples <a href="#di--closures">here</a>.</p>
<h2 id="why-di">
  <a href="#why-di">Why DI</a>
</h2>

<p>The problem I&rsquo;m trying to solve here is DI, or dependency injection. I have a function, class, or in this case route handler that needs access to a given resource, such as a database connection. As I do that, I have three aims:</p>
<ol>
<li>I want to wrap the database connection in an explicit interface to allow encapsulation — I don&rsquo;t want my routes to have to know how the database is structured, I just want them to be able to load and save e.g. <code>User</code> objects.</li>
<li>I want to be able to parameterize the database connection. When I run the code from my local machine, I want it to point to a local database, and when I run the code on production, I want it talking to the live database. That should happen automatically based on configuration files or environment variables.</li>
<li>I want to prevent code from having to construct its own dependencies (i.e. I want inversion of control). I don&rsquo;t want to create the database connection inside the route handler, I want that to happen outside the route and the result be passed to the route handler in some way.</li>
</ol>
<p>The solution to this is dependency injection, or DI. When I first started programming, this term confused me for a bit, because I&rsquo;d see lots of &ldquo;DI frameworks&rdquo; or similar tools, and I assumed that DI meant the act of using decorators or annotations to automatically inject parameters into the right place. This is not the case — those tools are often useful, but DI is more about how you write your code in the first place. For example, here are two Python functions, one of which uses DI:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">emails</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Function 1</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">send_emails</span><span class="p">(</span><span class="n">user</span><span class="p">:</span> <span class="n">User</span><span class="p">,</span> <span class="n">message</span><span class="p">:</span> <span class="nb">str</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="n">emails</span><span class="o">.</span><span class="n">EmailMailer</span><span class="p">()</span><span class="o">.</span><span class="n">send_email</span><span class="p">(</span><span class="n">user</span><span class="o">.</span><span class="n">email_address</span><span class="p">,</span> <span class="n">message</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">send_emails</span><span class="p">(</span><span class="n">User</span><span class="p">(</span><span class="n">name</span><span class="o">=</span><span class="s2">&#34;...&#34;</span><span class="p">,</span> <span class="n">email</span><span class="o">=</span><span class="s2">&#34;...&#34;</span><span class="p">),</span> <span class="s2">&#34;this is an email&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Function 2</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">send_emails</span><span class="p">(</span><span class="n">mailer</span><span class="p">:</span> <span class="n">EmailMailer</span><span class="p">,</span> <span class="n">user</span><span class="p">:</span> <span class="n">User</span><span class="p">,</span> <span class="n">message</span><span class="p">:</span> <span class="nb">str</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="n">mailer</span><span class="o">.</span><span class="n">send</span><span class="p">(</span><span class="n">user</span><span class="o">.</span><span class="n">email_address</span><span class="p">,</span> <span class="n">message</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">mailer</span> <span class="o">=</span> <span class="n">emails</span><span class="o">.</span><span class="n">EmailMailer</span><span class="p">(</span><span class="o">**</span><span class="n">email_params</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">send_emails</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">    <span class="n">mailer</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">user</span><span class="o">=</span><span class="n">User</span><span class="p">(</span><span class="n">name</span><span class="o">=</span><span class="s2">&#34;...&#34;</span><span class="p">,</span> <span class="n">email</span><span class="o">=</span><span class="s2">&#34;...&#34;</span><span class="p">),</span>
</span></span><span class="line"><span class="cl">    <span class="n">message</span><span class="o">=</span><span class="s2">&#34;this is an email&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span>
</span></span></code></pre></div><p>I think this is a good example, because you can see the advantages and disadvantages of DI. In this example, the second function uses DI, and the first function does not. The thing that jumps out the most to me is that the DI example is much more verbose — it takes more code, and it makes function signatures more complicated because they&rsquo;re taking more parameters. Partly that&rsquo;s just how I&rsquo;ve written these examples, but I do think DI adds complexity — useful complexity, but complexity nonetheless. You don&rsquo;t need DI if it&rsquo;s not adding value.</p>
<p>However, there are some benefits visible in the second function. By making the <code>EmailMailer</code> object explicit and bringing it out of the <code>send_emails</code> function, we can now more easily pass parameters to it. If multiple functions are all using the <code>EmailMailer</code> object, and we need to change how we configure it, then now we can do that configuration in one place, rather than at every place that it&rsquo;s used. (Alternatively, before we might have used some global configuration, but with DI, we can be more explicit.)</p>
<p>We can also swap out the mailer object that we use. I think this is often oversold as an advantage (how often do you really swap out implementations like this?) but it&rsquo;s often useful for testing. If we want to test the first <code>send_emails</code> function, we&rsquo;d have to mock a bunch of global imports, but with the second, we can just call the function with a mocked parameter.</p>
<p>The most important thing to notice here is that Function 2 uses dependency injection without going near a DI framework — without even using a single decorator! At its core, DI is just moving things from being constructed inside functions, to being constructed outside functions, and then figuring out how best to pass them back in.</p>
<p>Note that I&rsquo;ve used functions here, but classes work in much the same way. Typically, parameters can be passed to the class constructor (<code>__init__()</code>, <code>constructor()</code>, etc), and then attach as instance attributes (<code>self.param</code>, <code>this.#param</code>, etc). I&rsquo;m not going to use that style in this example, but I often use it for service objects.</p>
<p>With that out of the way, this is a way of doing DI via closures.</p>
<h2 id="di--closures">
  <a href="#di--closures">DI &amp; Closures</a>
</h2>

<p>Here&rsquo;s a couple examples of route definitions in FastAPI/Python and in Express/JS:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">fastapi</span> <span class="kn">import</span> <span class="n">FastAPI</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">app</span> <span class="o">=</span> <span class="n">FastAPI</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nd">@app.get</span><span class="p">(</span><span class="s2">&#34;/items/</span><span class="si">{item_id}</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="k">async</span> <span class="k">def</span> <span class="nf">read_item</span><span class="p">(</span><span class="n">item_id</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="c1"># ... TODO: get item value from a database somewhere</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="p">{</span><span class="s2">&#34;value&#34;</span><span class="p">:</span> <span class="o">...</span><span class="p">}</span>
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-js" data-lang="js"><span class="line"><span class="cl"><span class="kr">import</span> <span class="nx">express</span> <span class="nx">from</span> <span class="s2">&#34;express&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="kr">const</span> <span class="nx">app</span> <span class="o">=</span> <span class="nx">express</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nx">app</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s2">&#34;/items/:itemId&#34;</span><span class="p">,</span> <span class="p">(</span><span class="nx">req</span><span class="p">,</span> <span class="nx">res</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="c1">// ... TODO: get item value from a database somewhere
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>  <span class="nx">res</span><span class="p">.</span><span class="nx">json</span><span class="p">({</span> <span class="nx">value</span><span class="o">:</span> <span class="cm">/* ... */</span> <span class="p">});</span>
</span></span><span class="line"><span class="cl"><span class="p">});</span>
</span></span></code></pre></div><p>As discussed above, dependency injection is about passing parameters to functions. But in the two functions here, that&rsquo;s difficult, because the parameters are fixed, and we don&rsquo;t actually call the functions. For example, with the Express example, Express will always call our route handler with the <code>req</code> and <code>res</code>. There&rsquo;s no place to inject any services or dependencies of our own.</p>
<p>One option might be to attach our dependencies to the parameters. This is common in Express, where middleware can be used to dynamically add a <code>req.users</code> or <code>req.conn</code> attribute that can be accessed inside the routes. However, this can be error-prone, not least because it isn&rsquo;t compatible with Typescript unless you start modifying global types.</p>
<p>An easier option, at least for simple cases, is often just to use closures to capture the dependencies. Here are some examples to show what I mean:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">fastapi</span> <span class="kn">import</span> <span class="n">FastAPI</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">app</span> <span class="o">=</span> <span class="n">FastAPI</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">add_routes</span><span class="p">(</span><span class="n">app</span><span class="p">:</span> <span class="n">FastAPI</span><span class="p">,</span> <span class="o">*</span><span class="p">,</span> <span class="n">item_store</span><span class="p">:</span> <span class="n">ItemStore</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="nd">@app.get</span><span class="p">(</span><span class="s2">&#34;/items/</span><span class="si">{item_id}</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="k">async</span> <span class="k">def</span> <span class="nf">read_item</span><span class="p">(</span><span class="n">item_id</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">        <span class="n">item</span> <span class="o">=</span> <span class="k">await</span> <span class="n">item_store</span><span class="o">.</span><span class="n">load</span><span class="p">(</span><span class="n">item_id</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="p">{</span><span class="s2">&#34;value&#34;</span><span class="p">:</span> <span class="n">item</span><span class="o">.</span><span class="n">value</span><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">item_store</span> <span class="o">=</span> <span class="n">ItemStore</span><span class="p">(</span><span class="n">db</span><span class="o">=...</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">add_routes</span><span class="p">(</span><span class="n">app</span><span class="p">,</span> <span class="n">item_store</span><span class="o">=</span><span class="n">item_store</span><span class="p">)</span>
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-ts" data-lang="ts"><span class="line"><span class="cl"><span class="kr">import</span> <span class="nx">express</span> <span class="kr">from</span> <span class="s2">&#34;express&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="kr">const</span> <span class="nx">app</span> <span class="o">=</span> <span class="nx">express</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">function</span> <span class="nx">addRoutes</span><span class="p">(</span><span class="nx">app</span>: <span class="kt">Express</span><span class="p">,</span> <span class="nx">itemStore</span>: <span class="kt">ItemStore</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nx">app</span><span class="p">.</span><span class="kr">get</span><span class="p">(</span><span class="s2">&#34;items/:itemId&#34;</span><span class="p">,</span> <span class="kr">async</span> <span class="p">(</span><span class="nx">req</span><span class="p">,</span> <span class="nx">res</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="kr">const</span> <span class="nx">item</span> <span class="o">=</span> <span class="k">await</span> <span class="nx">itemStore</span><span class="p">.</span><span class="nx">load</span><span class="p">(</span><span class="nx">item_id</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="nx">res</span><span class="p">.</span><span class="nx">json</span><span class="p">({</span> <span class="nx">value</span>: <span class="kt">item.value</span> <span class="p">});</span>
</span></span><span class="line"><span class="cl">  <span class="p">});</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kr">const</span> <span class="nx">itemStore</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">ItemStore</span><span class="p">(</span><span class="nx">db</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="nx">addRoutes</span><span class="p">(</span><span class="nx">app</span><span class="p">,</span> <span class="nx">itemStore</span><span class="p">);</span>
</span></span></code></pre></div><p>The basic idea is that we move the route definitions from being defined at the top-level to being defined inside a function. The inner functions are now closures — when the function is called, the inner functions will have access to variables defined in the outer scope (in this case the parameters), and so can access the dependencies they need. We can then create all the dependencies, as well as the main app beforehand, and pass them to the <code>addRoutes</code> function.</p>
<p>In practice, I often have a <code>create_context()</code> function that loads configuration from somewhere, creates all the dependencies, and returns <code>Context</code> object or <a href="https://docs.python.org/3/library/typing.html#typing.TypedDict">typed dictionary</a> which contains all of the dependencies with keys. Then I can pass that whole context object to builder functions like <code>add_routes()</code>, rather than specifying all the dependencies individually.</p>
<p>Sometimes I also move the <code>app = FastAPI()</code>/<code>const app = express()</code> line inside the builder function, and have it return the entire app. I don&rsquo;t think one is better than the other, and which I use depends mostly on my mood.</p>
<h2 id="where-this-works-well-or-doesnt">
  <a href="#where-this-works-well-or-doesnt">Where This Works Well, or Doesn&rsquo;t</a>
</h2>

<p>I&rsquo;ve used web routing as an example here, but I find this works well enough in any situation where I can&rsquo;t easily pass something in via function parameters. Most languages I use — even quite static ones like Rust — allow functions to be defined within other functions like this. The key requirement is good support of closures, but this is also fairly standard at this point.</p>
<p>There is an issue if you also want to export the functions somehow. With the <code>FastAPI</code> example above, if we wanted to import the <code>read_item</code> function somewhere else and call it, that becomes very hard with closures. In this case, that&rsquo;s not a problem, but I&rsquo;ve run into contexts where it&rsquo;s more of an issue. In cases like that, I try to decouple the function entirely from any dependencies it needs, and just pass in raw data.</p>
<p>I&rsquo;ve also noticed that this can be harder to implement correctly in some cases with Rust, if the lifetimes don&rsquo;t match or the type is difficult to name correctly. Typically Rc/Arc + Clone for services solves most issues, and sometimes boxing up the return value is necessary.</p>
<h2 id="alternatives">
  <a href="#alternatives">Alternatives</a>
</h2>

<p>Of course this isn&rsquo;t the only way! Here are some other options that I also have in mind when deciding how to get my dependencies injected.</p>
<ul>
<li>No dependency injection at all — I find this works really well up to a point, and then it stops working fast, usually around the point I&rsquo;m configuring multiple DBs/external services, and want to get everything running in multiple environments. But simple is better the complicated, and no DI is simpler than DI.</li>
<li>Using module-level values. In Javascript, for example, I can export a value, as in <code>export const USERS = new UserService()</code>. Similar things are possible in Python and most other more dynamic scripting languages. This can be used instead of DI, and most languages have some way of mocking static module exports, so you can still swap in test implementations. But I find this often ends up quite hacky, and the dependency nest can get quite deep, so I try to avoid this these days.</li>
<li>A lot of frameworks provide some kind of app context field or value, which can be dynamically updated with different services or connections. Personally, I find it hard to keep track of what&rsquo;s on the context and what isn&rsquo;t, and I&rsquo;ve rarely found a simple way of handling this when I&rsquo;m using types.</li>
<li>FastAPI has something it calls DI, but is really just request extractor — it is called for each request, it is passed the request, and it extracts the details it needs. I personally haven&rsquo;t had much success using this feature for DI proper. That said, other frameworks do provide a full DI framework. If it&rsquo;s built into the framework, then I tend to follow the &ldquo;when it Rome, do as the Romans&rdquo; principle.</li>
<li>If all else fails, there are lots of DI libraries. I tend to avoid these, because it&rsquo;s added complexity when just passing in functions works well enough. But sometimes you get to the point where constructing all your services and dependencies up front doesn&rsquo;t cut it, and you need something more powerful. I&rsquo;ve not reached that point myself, but most of the projects I&rsquo;ve worked on have been relatively small.</li>
</ul>
<h2 id="conclusion">
  <a href="#conclusion">Conclusion</a>
</h2>

<p>I hope this was helpful, this is just one strategy that I&rsquo;ve found useful for doing simple DI without having to lean into frameworks or have annotation/decorator-based magic.</p>
]]></content:encoded></item></channel></rss>