Matt MachugaI like to build things and help peoplehttp://matthewmachuga.com/blog2019-03-22T00:00:00+00:00Matt MachugaThe JavaScript Event Loophttp://matthewmachuga.com/blog/2019/the-javascript-event-loop.html2019-03-22T00:00:00+00:002023-11-10T13:34:59+00:00Matt Machuga<p>A wild JavaScript code snippet appears!</p>
<div class="highlight"><pre class="highlight javascript"><code><span class="kd">const</span> <span class="nx">log</span> <span class="o">=</span> <span class="p">(</span><span class="nx">output</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span> <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s2">`--</span><span class="p">${</span><span class="nx">output</span><span class="p">}</span><span class="s2">--`</span><span class="p">);</span> <span class="p">};</span>
<span class="nx">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">first</span><span class="dl">"</span><span class="p">);</span>
<span class="nx">setTimeout</span><span class="p">(</span><span class="kd">function</span> <span class="nx">fifth</span><span class="p">()</span> <span class="p">{</span> <span class="nx">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">fifth</span><span class="dl">"</span><span class="p">);</span> <span class="p">},</span> <span class="mi">500</span><span class="p">);</span>
<span class="nx">setTimeout</span><span class="p">(</span><span class="kd">function</span> <span class="nx">third</span><span class="p">()</span> <span class="p">{</span> <span class="nx">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">third</span><span class="dl">"</span><span class="p">);</span> <span class="p">},</span> <span class="mi">0</span><span class="p">);</span>
<span class="nx">setTimeout</span><span class="p">(</span><span class="kd">function</span> <span class="nx">fourth</span><span class="p">()</span> <span class="p">{</span> <span class="nx">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">fourth</span><span class="dl">"</span><span class="p">);</span> <span class="p">},</span> <span class="mi">0</span><span class="p">);</span>
<span class="nx">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">second</span><span class="dl">"</span><span class="p">);</span>
</code></pre></div>
<p>For a boss-fight JavaScript code snippet that has more use cases, please
<a href="https://gist.github.com/machuga/e0dae53637be1ed6b3a97923cfadc775#file-eventloop-boss-fight-js">check out this
gist</a></p>
<h2>Spoiler Alert / TL;DR</h2>
<p>I have the order of execution given out as <code>first</code> through <code>fifth</code> for clarity
and to make it so readers can skim this and be on their way when they need a
reference.</p>
<h2>Slightly More TL;DR</h2>
<p>JavaScript will run a function until completion (ignoring iterators), so there
is no JS-level function interleaving. This means that you will not run into the
same race conditions you may hit in C, C++, or other languages with threading.
The JS engine under the hood is indeed using threads and waiting for
asynchronous actions concurrently; however, JS-level code will run top-down
sequentially in the current stack frame.</p>
<h2>Order Matters</h2>
<p>JavaScript, as mentioned in previous blog posts (and above in the second TL;DR
section), executes from top to bottom. That means that in our above snippet,
every line is going to get executed before any other JavaScript in the same
process is executed.</p>
<h2>We’re All JavaScript Runtimes</h2>
<p>So on line 1, we define a function that we assign to the
variable <code>log</code> that adds some extra formatting to a standard <code>console.log</code>
call. Great! Now we can use that throughout our code.</p>
<p>So we proceed to line 3, which invokes this new function and passes along the
string <code>first</code> to be output to the console. Because both <code>log</code> and <code>console.log</code> are
synchronous functions, meaning they do not escape the event loop, this code will
first evaluate <code>log</code>, enter the function, evaluate <code>console.log</code> which is
native code, and then return <code>undefined</code> from both function because we do not
specify a return value.</p>
<p>The JS runtime does not move onto anything else during this time, it only
evaluates this code. After it returns it is free to move on to line 5:</p>
<div class="highlight"><pre class="highlight javascript"><code><span class="nx">setTimeout</span><span class="p">(</span><span class="kd">function</span> <span class="nx">fifth</span><span class="p">()</span> <span class="p">{</span> <span class="nx">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">fifth</span><span class="dl">"</span><span class="p">);</span> <span class="p">},</span> <span class="mi">500</span><span class="p">);</span>
</code></pre></div>
<p>This is where things start to break down the 4th wall and start reaching
into asynchronous territory. <code>setTimeout</code> is a magical function (no, not
really) that sets a timer with the JS runtime. The JS runtime effectively sets
an eggtimer for <code>500</code> milliseconds, puts it down on a counter, and then returns
back to the calling function. Unlike my <code>log</code> function, <code>setTimeout</code> actually
does have a return value - an identifier of the timer it just set. It’s outside
of the scope of this demo, but if you wanted to cancel your timer, you could
run <code>clearTimeout(idOfTimeout)</code>, and the callback you passed would never be
executed. But I digress.</p>
<p>Anyway, now we’ve returned from the first <code>setTimeout</code> and proceed to the next.
It is largely the same as the last call, except for one notable difference:</p>
<div class="highlight"><pre class="highlight javascript"><code><span class="nx">setTimeout</span><span class="p">(</span><span class="kd">function</span> <span class="nx">third</span><span class="p">()</span> <span class="p">{</span> <span class="nx">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">third</span><span class="dl">"</span><span class="p">);</span> <span class="p">},</span> <span class="mi">0</span><span class="p">);</span>
</code></pre></div>
<p>The timeout is set to <code>0</code>. What does your gut tell you will happen here? The
timeout is set to <code>0</code> milliseconds, so hypothetically that could mean <code>run
right now</code>. However, that is not the case. <code>setTimeout</code> sets a timer in the
background, and those timers cannot be executed until the current block of
JavaScript code has completed execution. So, the same metaphorical eggtimer
gets set, with a time of <code>0</code>. So even if the timer goes off by the time we
return from this timeout, our friendly runtime can’t do anything about it
because we are blocking the runloop with our pesky code. Well let’s carry on
then.</p>
<p>The next line is the same as the one before, I just wanted to make a point of
it to show that these messages get stacked up on a queue and will get executed
in the order they’re dropped into the timer. So in this situation, these
functions will be run in their respective numerical order. Perfect.</p>
<p>Finally we run into our last line:</p>
<div class="highlight"><pre class="highlight javascript"><code><span class="nx">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">second</span><span class="dl">"</span><span class="p">);</span>
</code></pre></div>
<p>This call says <code>second</code>, but is the last line of the file. And it is even
correct! When this program runs, it will be the second line of code to write
text to the console because it is synchronous, like the first call to <code>log</code>. So
it’s going to execute, write code to your console, return, and then this block
of JavaScript has completed execution!</p>
<p>The console output at this point will look like this:</p>
<div class="highlight"><pre class="highlight plaintext"><code>--first--
--second--
</code></pre></div>
<p>If this was run with NodeJS, and there
were no timers or other event listeners configured, your program would now
exit because its work is done.</p>
<p>However, we setup three different timers, so its work is not yet complete.
Since there was a <code>0</code> millisecond delay (remembering from previous posts that
in JavaScript this means <em>at least</em> <code>0</code>, not exactly <code>0</code>) from our second and
third <code>setTimeout</code> calls, our runtime can finally put those eggtimers away
and will run the functions we passed into those <code>setTimeout</code> calls. Our output
will now look like this:</p>
<div class="highlight"><pre class="highlight plaintext"><code>--first--
--second--
--third--
--fourth--
</code></pre></div>
<p>Our runtime is just going to hang out for a bit, waiting for something else to
happen. In this sitation, there is nothing else waiting to run except for tour
timer. So after a grueling <code>500</code> milliseconds (at least <code>500</code> from when it was
set, our final timer will go off, and the callback passed in will execute,
leaving us with the final console output:</p>
<div class="highlight"><pre class="highlight plaintext"><code>--first--
--second--
--third--
--fourth--
--fifth--
</code></pre></div>
<p>At this point, the runtime’s work is done and as it bids you adieu the program
will exit.</p>
<h2>The More You Know</h2>
<p>This is the basic formula for how asynchronous actions in the event loop
functions. Network calls, file operations, event callbacks, etc.
all behave similarly. They have functions implemented at the native level
that allow access to a three underlying runtime’s thread pool and can dispatch
actions outside of the main JS thread. When they call back, the JS runtime
receives an event, and at the next tick, or iteration of the event loop, those
events will have a chance to execute. I’ve included a link below to how
NodeJS’s event loop runs, which covers the various phases it includes. Browser
runtimes function similarly but may have different phases or timings.</p>
<h2>Resources and Citations</h2>
<p>There are many excellent resources for deep explanations of event loops.
These two are my favorite:</p>
<ul>
<li><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/EventLoop">MDN Concurrency model and Event Loop</a></li>
<li><a href="https://nodejs.org/en/docs/guides/event-loop-timers-and-nexttick/">The NodeJS Event Loop Official Docs</a></li>
</ul>
Waiting on Multiple Callbackshttp://matthewmachuga.com/blog/2019/waiting-on-multiple-callbacks.html2019-02-18T23:59:00+00:002023-11-10T13:34:59+00:00Matt Machuga<p>First, a refresher on asynchronous functions utilizing callbacks:</p>
<div class="highlight"><pre class="highlight javascript"><code><span class="nx">setTimeout</span><span class="p">(()</span> <span class="o">=></span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">One second later</span><span class="dl">'</span><span class="p">);</span>
<span class="p">},</span> <span class="mi">1000</span><span class="p">);</span>
</code></pre></div>
<p>The above code will log <code>One second later</code> to the console after at least a one
second delay (timing isn’t precise in JS, but it’ll usually be close…but I
digress). <code>setTimeout</code> accepts a callback to be executed after a set number of
milliseconds that are passed in as the second argument. We, the developer of a
JavaScript application, do not need to be concerned what happens inside of the
<code>setTimeout</code> function, we just need to understand that the event loop will
continue running, and after <code>1000</code> milliseconds our callback will be executed.</p>
<p>Plenty simple! But what happens when you have a number of asynchronous actions
you need completed before performing another action? Well in JavaScript proper,
there are no primitives for handling this situation with callbacks. You are
left to implement this logic on your own (or use a convenient library like
<code>async</code>, which is linked at the bottom). But never fear! If you’ve read the
past article you’ve already seen the code to handle this. This time we’ll walk
through how and why this works.</p>
<p>Let’s start off by assuming we have an array of four numbers representing
milliseconds.</p>
<div class="highlight"><pre class="highlight javascript"><code><span class="kd">const</span> <span class="nx">durations</span> <span class="o">=</span> <span class="p">[</span><span class="mi">250</span><span class="p">,</span> <span class="mi">500</span><span class="p">,</span> <span class="mi">750</span><span class="p">,</span> <span class="mi">1000</span><span class="p">];</span>
</code></pre></div>
<p>Next we’re going to create a function that:</p>
<ol>
<li>Takes an array of <code>n</code> numbers</li>
<li>Creates <code>n</code> timeouts based on the values in the array</li>
<li>Each timeout will output its duration upon completion</li>
<li>Upon all timeouts completing, will execute a callback that was passed in.</li>
</ol>
<div class="highlight"><pre class="highlight javascript"><code><span class="kd">const</span> <span class="nx">createTimeouts</span> <span class="o">=</span> <span class="p">(</span><span class="nx">durations</span><span class="p">,</span> <span class="nx">callback</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span>
<span class="kd">let</span> <span class="nx">remainingCount</span> <span class="o">=</span> <span class="nx">durations</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span>
<span class="nx">durations</span><span class="p">.</span><span class="nx">forEach</span><span class="p">((</span><span class="nx">duration</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span>
<span class="nx">setTimeout</span><span class="p">(()</span> <span class="o">=></span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s2">`I completed in </span><span class="p">${</span><span class="nx">duration</span><span class="p">}</span><span class="s2"> milliseconds`</span><span class="p">);</span>
<span class="nx">remainingCount</span> <span class="o">-=</span> <span class="mi">1</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">remainingCount</span> <span class="o"><=</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">callback</span><span class="p">();</span>
<span class="p">}</span>
<span class="p">},</span> <span class="nx">duration</span><span class="p">);</span>
<span class="p">});</span>
<span class="p">}</span>
</code></pre></div>
<p>Finally, we’ll invoke the function and pass in a function that will write out
to the console <code>We are all done!</code>. So if we save the whole thing:</p>
<div class="highlight"><pre class="highlight javascript"><code><span class="kd">const</span> <span class="nx">durations</span> <span class="o">=</span> <span class="p">[</span><span class="mi">250</span><span class="p">,</span> <span class="mi">500</span><span class="p">,</span> <span class="mi">750</span><span class="p">,</span> <span class="mi">1000</span><span class="p">];</span>
<span class="kd">const</span> <span class="nx">createTimeouts</span> <span class="o">=</span> <span class="p">(</span><span class="nx">durations</span><span class="p">,</span> <span class="nx">callback</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span>
<span class="kd">let</span> <span class="nx">remainingCount</span> <span class="o">=</span> <span class="nx">durations</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span>
<span class="nx">durations</span><span class="p">.</span><span class="nx">forEach</span><span class="p">((</span><span class="nx">duration</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span>
<span class="nx">setTimeout</span><span class="p">(()</span> <span class="o">=></span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s2">`I completed in </span><span class="p">${</span><span class="nx">duration</span><span class="p">}</span><span class="s2"> milliseconds`</span><span class="p">);</span>
<span class="nx">remainingCount</span> <span class="o">-=</span> <span class="mi">1</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">remainingCount</span> <span class="o"><=</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">callback</span><span class="p">();</span>
<span class="p">}</span>
<span class="p">},</span> <span class="nx">duration</span><span class="p">);</span>
<span class="p">});</span>
<span class="p">}</span>
<span class="nx">createTimeouts</span><span class="p">(</span><span class="nx">durations</span><span class="p">,</span> <span class="p">()</span> <span class="o">=></span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">We are all done!</span><span class="dl">"</span><span class="p">);</span>
<span class="p">});</span>
</code></pre></div>
<p>and then execute the script, we’ll see each timeout execute in order every
quarter second, with <code>1000</code> being swiftly followed by <code>We are all done!</code></p>
<div class="highlight"><pre class="highlight plaintext"><code>I completed in 250 milliseconds
I completed in 500 milliseconds
I completed in 750 milliseconds
I completed in 1000 milliseconds
We are all done!
</code></pre></div>
<p>There is no magic here! We’re using an integer, <code>remainingCount</code> set to the
length of the number of callbacks we’re going to execute. Then on every
callback execution we decrement <code>remainingCount</code> by one, and subsequently check
to see if we’ve reached <code>0</code>. If not, we keep going, but if <code>0</code> has indeed been
reached we’re going to call the callback that’s been passed into the
<code>createTimeouts</code> function to let the caller know that everything’s been
completed.</p>
<p>Was that a bit underwhelming? Like most things in computer science, this
potentially challenging problem could be solved with a little bit of math.
Lucky for us!</p>
<h2>Handling <code>n</code> Functions Generically (and Naively)</h2>
<p>Maybe you don’t want to write this looping code every time - maybe you are
worried you may make a mistake, or you prefer not utilizing imperative
constructs when possible. We can turn this into a generic helper pretty
quickly, but we should define what we want first since there are many different
ways we may want this information returned.</p>
<p>I want to create a function, we’ll call it <code>whenAllSettled</code>, that will accept a
list of functions accepting node-style callbacks <code>(err, result) => {}</code>, and
will execute each one in order. All executions, whether successful
or failures, will store an object with the keys <code>type</code> and <code>value</code> into a list
<code>results</code>. When no error is raised, the <code>type</code> key will be set to <code>success</code>,
and <code>value</code> set to whatever <code>result</code> was in the callback. When an error was
thrown, we will set <code>type</code> to <code>failure</code> and <code>value</code> to be the <code>Error</code> object
sent to the callback.</p>
<p>To test it out, we’ll nest two levels of <code>whenAllSettled</code> to demonstrate that
it will wait for all of the first callbacks to complete, and that it can be
nested to wait in different ways.</p>
<p>Let’s see what this looks like:</p>
<div class="highlight"><pre class="highlight javascript"><code><span class="kd">const</span> <span class="nx">whenAllSettled</span> <span class="o">=</span> <span class="p">(</span><span class="nx">fns</span><span class="p">,</span> <span class="nx">callback</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span>
<span class="kd">const</span> <span class="nx">results</span> <span class="o">=</span> <span class="p">[];</span>
<span class="kd">let</span> <span class="nx">remainingCount</span> <span class="o">=</span> <span class="nx">fns</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span>
<span class="kd">const</span> <span class="nx">done</span> <span class="o">=</span> <span class="p">(</span><span class="nx">err</span><span class="p">,</span> <span class="nx">result</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span>
<span class="kd">let</span> <span class="nx">resultObject</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">err</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">resultObject</span> <span class="o">=</span> <span class="p">{</span> <span class="na">type</span><span class="p">:</span> <span class="dl">'</span><span class="s1">failure</span><span class="dl">'</span><span class="p">,</span> <span class="na">value</span><span class="p">:</span> <span class="nx">err</span> <span class="p">};</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="nx">resultObject</span> <span class="o">=</span> <span class="p">{</span> <span class="na">type</span><span class="p">:</span> <span class="dl">'</span><span class="s1">success</span><span class="dl">'</span><span class="p">,</span> <span class="na">value</span><span class="p">:</span> <span class="nx">result</span> <span class="p">};</span>
<span class="p">}</span>
<span class="nx">results</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">resultObject</span><span class="p">);</span>
<span class="nx">remainingCount</span> <span class="o">-=</span> <span class="mi">1</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">remainingCount</span> <span class="o"><=</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">callback</span><span class="p">(</span><span class="kc">null</span><span class="p">,</span> <span class="nx">results</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">};</span>
<span class="nx">fns</span><span class="p">.</span><span class="nx">forEach</span><span class="p">((</span><span class="nx">fn</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span>
<span class="nx">fn</span><span class="p">(</span><span class="nx">done</span><span class="p">)</span>
<span class="p">});</span>
<span class="p">}</span>
<span class="kd">const</span> <span class="nx">callbacks</span> <span class="o">=</span> <span class="p">[</span>
<span class="p">(</span><span class="nx">done</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span> <span class="nx">setTimeout</span><span class="p">(()</span> <span class="o">=></span> <span class="p">{</span> <span class="nx">done</span><span class="p">(</span><span class="kc">null</span><span class="p">,</span> <span class="dl">'</span><span class="s1">1</span><span class="dl">'</span><span class="p">)</span> <span class="p">},</span> <span class="mi">500</span><span class="p">)</span> <span class="p">},</span>
<span class="p">(</span><span class="nx">done</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span> <span class="nx">setTimeout</span><span class="p">(()</span> <span class="o">=></span> <span class="p">{</span> <span class="nx">done</span><span class="p">(</span><span class="kc">null</span><span class="p">,</span> <span class="dl">'</span><span class="s1">2</span><span class="dl">'</span><span class="p">)</span> <span class="p">},</span> <span class="mi">200</span><span class="p">)</span> <span class="p">},</span>
<span class="p">];</span>
<span class="nx">whenAllSettled</span><span class="p">(</span><span class="nx">callbacks</span><span class="p">,</span> <span class="p">(</span><span class="nx">err</span><span class="p">,</span> <span class="nx">results</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">All done with round 1!</span><span class="dl">"</span><span class="p">,</span> <span class="nx">results</span><span class="p">);</span>
<span class="nx">whenAllSettled</span><span class="p">([</span>
<span class="p">(</span><span class="nx">done</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span> <span class="nx">setTimeout</span><span class="p">(()</span> <span class="o">=></span> <span class="nx">done</span><span class="p">(</span><span class="k">new</span> <span class="nb">Error</span><span class="p">(</span><span class="dl">'</span><span class="s1">oops</span><span class="dl">'</span><span class="p">)),</span> <span class="mi">500</span><span class="p">);</span> <span class="p">}</span>
<span class="p">],</span> <span class="p">(</span><span class="nx">err</span><span class="p">,</span> <span class="nx">results</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">All done with round 2!</span><span class="dl">"</span><span class="p">,</span> <span class="nx">results</span><span class="p">);</span>
<span class="p">})</span>
<span class="p">});</span>
</code></pre></div>
<p>Now if we run this code we can watch the output pop up over time:</p>
<div class="highlight"><pre class="highlight plaintext"><code>All done with round 1! [ { type: 'success', value: '2' }, { type: 'success', value: '1' } ]
All done with round 2! [ { type: 'failure',
value:
Error: oops
at Timeout.setTimeout [as _onTimeout] (/Users/machuga/src/book-examples/multipleCallbacksGeneric.js:37:37)
at listOnTimeout (timers.js:324:15)
at processTimers (timers.js:268:5) } ]
</code></pre></div>
<p>So that’s cool - our functions wait till the appropriate time to execute, and
both successes and failures get returned properly. But if you are looking
carefully, you’ll notice something a bit out of place.</p>
<div class="highlight"><pre class="highlight javascript"><code><span class="kd">const</span> <span class="nx">callbacks</span> <span class="o">=</span> <span class="p">[</span>
<span class="p">(</span><span class="nx">done</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span> <span class="nx">setTimeout</span><span class="p">(()</span> <span class="o">=></span> <span class="p">{</span> <span class="nx">done</span><span class="p">(</span><span class="kc">null</span><span class="p">,</span> <span class="dl">'</span><span class="s1">1</span><span class="dl">'</span><span class="p">)</span> <span class="p">},</span> <span class="mi">500</span><span class="p">)</span> <span class="p">},</span>
<span class="p">(</span><span class="nx">done</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span> <span class="nx">setTimeout</span><span class="p">(()</span> <span class="o">=></span> <span class="p">{</span> <span class="nx">done</span><span class="p">(</span><span class="kc">null</span><span class="p">,</span> <span class="dl">'</span><span class="s1">2</span><span class="dl">'</span><span class="p">)</span> <span class="p">},</span> <span class="mi">200</span><span class="p">)</span> <span class="p">},</span>
<span class="p">];</span>
</code></pre></div>
<p>At the top we defined the <code>callbacks</code> array with two functions, the first
executed <code>done</code> with <code>1</code>, and the second with <code>2</code>; however, in our output we
can see that <code>2</code> was returned first and <code>1</code> came in after. This is because the
timeout for the first callback was longer (<code>500</code>) than the second (<code>200</code>). The
fact that the results can be returned out of their executed order can cause
non-deterministic results from our function - we can’t be sure which
data comes from which function.</p>
<h2>How to Maintain Order</h2>
<p>So we know that if we have callbacks firing whenever they please, and then the
results are being inserted into an array at that time, there is no guarantee on
what order our callbacks will be in. So we need a way to track the order as we
add them to our list of results. Courtesy of indexing into arrays, this is pretty
straight forward.</p>
<p>We’re going to change our iteration over the callback functions:</p>
<div class="highlight"><pre class="highlight javascript"><code><span class="nx">fns</span><span class="p">.</span><span class="nx">forEach</span><span class="p">((</span><span class="nx">fn</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span>
<span class="nx">fn</span><span class="p">(</span><span class="nx">done</span><span class="p">);</span>
<span class="p">});</span>
</code></pre></div>
<p>to also pass in the index to the looping function. If you haven’t seen it before,
the function passed to <code>forEach</code> takes more than one argument. The first argument
is the value, but the second value is the index. So we’re going to take that index
and pass it along to the <code>done</code> function. Our loop will now look like this:</p>
<div class="highlight"><pre class="highlight javascript"><code><span class="nx">fns</span><span class="p">.</span><span class="nx">forEach</span><span class="p">((</span><span class="nx">fn</span><span class="p">,</span> <span class="nx">i</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span>
<span class="nx">fn</span><span class="p">(</span><span class="nx">done</span><span class="p">(</span><span class="nx">i</span><span class="p">));</span>
<span class="p">});</span>
</code></pre></div>
<p>If you recall, our <code>done</code> function only accepts an <code>err</code> and a <code>result</code>, so we will
need to modify it to instead <em>return</em> a function that accepts an <code>err</code> and a <code>result</code>.
<code>done</code> will now accept an integer, and instead of running</p>
<div class="highlight"><pre class="highlight javascript"><code><span class="nx">results</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">resultObject</span><span class="p">);</span>
</code></pre></div>
<p>we will save directly to the index like this:</p>
<div class="highlight"><pre class="highlight javascript"><code><span class="nx">results</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span> <span class="o">=</span> <span class="nx">resultObject</span><span class="p">;</span>
</code></pre></div>
<p>Now when we rerun our script we’ll see our results are returned in the order in
which we passed in their functions.</p>
<div class="highlight"><pre class="highlight plaintext"><code>All done with round 1! [ { type: 'success', value: '1' }, { type: 'success', value: '2' } ]
</code></pre></div>
<p>You can view the final version
<a href="https://gist.github.com/machuga/e0dae53637be1ed6b3a97923cfadc775#file-callback-purgatory-2-multiple-callbacks-js">here</a>.</p>
<h2>Wrap Up</h2>
<p>So that’s how to make a function that will wait for <code>n</code> functions to complete
and pass their results into callback in the order they were given. Hope that helps remove
any of the magic feeling behind it.</p>
<p>However, you may not want to write this yourself every time you want to work on
some code with callbacks. Good news! There is an awesome library,
<a href="https://caolan.github.io/async/">async</a> that is capable of doing all of the asynchronous
magic with callbacks I’m going to demonstrate in this series! It’s been battle tested
for years, so it’s ready for you to use in your production code.</p>
<p>You may be wondering: if this all happens asynchronously, how can I
be sure that <code>remainingCount</code> will ever reach <code>0</code>? Or will not go further than <code>0</code>?
Can’t a race condition occur?</p>
<p>In the next article I’m going to walk through the basics of the
JavaScript event loop. We’ll ensure we have a solid working understanding before we continue
refactoring our asychronous code from earlier in the series.</p>
Extracting Functions and Shifting Lefthttp://matthewmachuga.com/blog/2019/extracting-functions-and-shifting-left.html2019-02-06T11:00:00+00:002023-11-10T13:34:59+00:00Matt Machuga<p>Let’s take a look at our example from last time:</p>
<div class="highlight"><pre class="highlight javascript"><code><span class="kd">const</span> <span class="kd">get</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="dl">'</span><span class="s1">./get</span><span class="dl">'</span><span class="p">);</span> <span class="c1">// get(url, callback)</span>
<span class="kd">const</span> <span class="nx">githubApi</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">https://api.github.com</span><span class="dl">'</span><span class="p">;</span>
<span class="kd">const</span> <span class="nx">githubEventsUrlFor</span> <span class="o">=</span> <span class="nx">username</span> <span class="o">=></span> <span class="s2">`</span><span class="p">${</span><span class="nx">githubApi</span><span class="p">}</span><span class="s2">/users/</span><span class="p">${</span><span class="nx">username</span><span class="p">}</span><span class="s2">/events`</span><span class="p">;</span>
<span class="kd">const</span> <span class="nx">githubRepoUrlFor</span> <span class="o">=</span> <span class="nx">repo</span> <span class="o">=></span> <span class="s2">`</span><span class="p">${</span><span class="nx">githubApi</span><span class="p">}</span><span class="s2">/repos/</span><span class="p">${</span><span class="nx">repo</span><span class="p">}</span><span class="s2">`</span><span class="p">;</span>
<span class="kd">const</span> <span class="nx">fetchReposForLatestActivity</span> <span class="o">=</span> <span class="p">(</span><span class="nx">user</span><span class="p">,</span> <span class="nx">callback</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span>
<span class="kd">let</span> <span class="nx">timeout</span> <span class="o">=</span> <span class="nx">setTimeout</span><span class="p">(</span><span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
<span class="nx">callback</span><span class="p">(</span><span class="k">new</span> <span class="nb">Error</span><span class="p">(</span><span class="dl">'</span><span class="s1">Timed out</span><span class="dl">'</span><span class="p">));</span>
<span class="p">},</span> <span class="mi">3000</span><span class="p">);</span>
<span class="kd">get</span><span class="p">(</span><span class="nx">githubEventsUrlFor</span><span class="p">(</span><span class="nx">user</span><span class="p">),</span> <span class="p">(</span><span class="nx">err</span><span class="p">,</span> <span class="nx">allEvents</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">err</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="nx">callback</span><span class="p">(</span><span class="nx">err</span><span class="p">);</span>
<span class="p">}</span>
<span class="kd">const</span> <span class="nx">events</span> <span class="o">=</span> <span class="nx">allEvents</span><span class="p">.</span><span class="nx">slice</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">3</span><span class="p">);</span>
<span class="kd">const</span> <span class="nx">repos</span> <span class="o">=</span> <span class="p">[];</span>
<span class="kd">let</span> <span class="nx">remainingCount</span> <span class="o">=</span> <span class="nx">events</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span>
<span class="nx">events</span><span class="p">.</span><span class="nx">forEach</span><span class="p">(</span><span class="nx">event</span> <span class="o">=></span> <span class="p">{</span>
<span class="kd">get</span><span class="p">(</span><span class="nx">githubRepoUrlFor</span><span class="p">(</span><span class="nx">event</span><span class="p">.</span><span class="nx">repo</span><span class="p">.</span><span class="nx">name</span><span class="p">),</span> <span class="p">(</span><span class="nx">err</span><span class="p">,</span> <span class="nx">data</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">err</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="nx">callback</span><span class="p">(</span><span class="nx">err</span><span class="p">);</span>
<span class="p">}</span>
<span class="nx">repos</span><span class="p">.</span><span class="nx">push</span><span class="p">({</span>
<span class="na">author</span><span class="p">:</span> <span class="nx">data</span><span class="p">.</span><span class="nx">owner</span><span class="p">.</span><span class="nx">login</span><span class="p">,</span>
<span class="na">avatar</span><span class="p">:</span> <span class="nx">data</span><span class="p">.</span><span class="nx">owner</span><span class="p">.</span><span class="nx">avatar_url</span><span class="p">,</span>
<span class="na">name</span><span class="p">:</span> <span class="nx">data</span><span class="p">.</span><span class="nx">name</span><span class="p">,</span>
<span class="na">full_name</span><span class="p">:</span> <span class="nx">data</span><span class="p">.</span><span class="nx">full_name</span><span class="p">,</span>
<span class="na">url</span><span class="p">:</span> <span class="nx">data</span><span class="p">.</span><span class="nx">html_url</span><span class="p">,</span>
<span class="na">description</span><span class="p">:</span> <span class="nx">data</span><span class="p">.</span><span class="nx">description</span>
<span class="p">});</span>
<span class="nx">remainingCount</span> <span class="o">-=</span> <span class="mi">1</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">remainingCount</span> <span class="o"><=</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">clearTimeout</span><span class="p">(</span><span class="nx">timeout</span><span class="p">);</span>
<span class="nx">callback</span><span class="p">(</span><span class="kc">null</span><span class="p">,</span> <span class="nx">repos</span><span class="p">)</span>
<span class="p">}</span>
<span class="p">});</span>
<span class="p">});</span>
<span class="p">});</span>
<span class="p">};</span>
<span class="nx">fetchReposForLatestActivity</span><span class="p">(</span><span class="dl">'</span><span class="s1">machuga</span><span class="dl">'</span><span class="p">,</span> <span class="p">(</span><span class="nx">err</span><span class="p">,</span> <span class="nx">repos</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">err</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">error</span><span class="p">(</span><span class="nx">err</span><span class="p">);</span>
<span class="k">return</span><span class="p">;</span>
<span class="p">}</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">repos</span><span class="p">);</span>
<span class="p">});</span>
</code></pre></div>
<p>We have a number of different nesting levels going on here and a lot of work
happening in one named function. As with most other areas of programming, this
code would probably do well to be broken apart into logical, well named
functions. But asynchronous code, especially in languages that are lexically
scoped like JavaScript, can sometimes be a bit more challenging to tease apart.
We will start with some low hanging fruit and then move to more involved
extractions in later posts.</p>
<h2>Extract HTTP Requests</h2>
<p>The first thing I want to do is extract the embedded HTTP requests into named
functions, that way it is clear what they are doing, and they are easier for us
to talk about. A win for both you the reader of this article and for people
who will eventually read your asynchronous code.</p>
<div class="highlight"><pre class="highlight javascript"><code><span class="kd">const</span> <span class="nx">fetchRepo</span> <span class="o">=</span> <span class="p">(</span><span class="nx">repoName</span><span class="p">,</span> <span class="nx">callback</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span>
<span class="kd">get</span><span class="p">(</span><span class="nx">githubRepoUrlFor</span><span class="p">(</span><span class="nx">repoName</span><span class="p">),</span> <span class="nx">callback</span><span class="p">);</span>
<span class="p">};</span>
<span class="kd">const</span> <span class="nx">fetchEventsForUser</span> <span class="o">=</span> <span class="p">(</span><span class="nx">user</span><span class="p">,</span> <span class="nx">callback</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span>
<span class="kd">get</span><span class="p">(</span><span class="nx">githubEventsUrlFor</span><span class="p">(</span><span class="nx">user</span><span class="p">),</span> <span class="nx">callback</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div>
<p>Something to note here is that I was able to pass the callback sent to our new
functions directly to the <code>get</code> call without an intermediate callback. Why does
this work? We left the invoking code expecting the same callback signature, and
all of our callbacks expect <code>(error, result)</code> as an argument list. So we can
save ourself a frame on the callstack (extra compute time and extra garbage to
be collected), and skip over reduncancy that would look like:</p>
<div class="highlight"><pre class="highlight javascript"><code><span class="kd">const</span> <span class="nx">fetchRepo</span> <span class="o">=</span> <span class="p">(</span><span class="nx">repoName</span><span class="p">,</span> <span class="nx">callback</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span>
<span class="kd">get</span><span class="p">(</span><span class="nx">githubRepoUrlFor</span><span class="p">(</span><span class="nx">repoName</span><span class="p">),</span> <span class="p">(</span><span class="nx">err</span><span class="p">,</span> <span class="nx">repo</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">err</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="nx">callback</span><span class="p">(</span><span class="nx">err</span><span class="p">);</span>
<span class="p">}</span>
<span class="nx">callback</span><span class="p">(</span><span class="kc">null</span><span class="p">,</span> <span class="nx">repo</span><span class="p">);</span>
<span class="p">});</span>
<span class="p">};</span>
</code></pre></div>
<p>This small set of extractions makes our main fetching function look like this:</p>
<div class="highlight"><pre class="highlight javascript"><code><span class="kd">const</span> <span class="nx">fetchReposForLatestActivity</span> <span class="o">=</span> <span class="p">(</span><span class="nx">user</span><span class="p">,</span> <span class="nx">callback</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span>
<span class="kd">let</span> <span class="nx">timeout</span> <span class="o">=</span> <span class="nx">setTimeout</span><span class="p">(</span><span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
<span class="nx">callback</span><span class="p">(</span><span class="k">new</span> <span class="nb">Error</span><span class="p">(</span><span class="dl">'</span><span class="s1">Timed out</span><span class="dl">'</span><span class="p">));</span>
<span class="p">},</span> <span class="mi">3000</span><span class="p">);</span>
<span class="nx">fetchEventsForUser</span><span class="p">(</span><span class="nx">user</span><span class="p">,</span> <span class="p">(</span><span class="nx">err</span><span class="p">,</span> <span class="nx">allEvents</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">err</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="nx">callback</span><span class="p">(</span><span class="nx">err</span><span class="p">);</span>
<span class="p">}</span>
<span class="kd">const</span> <span class="nx">events</span> <span class="o">=</span> <span class="nx">allEvents</span><span class="p">.</span><span class="nx">slice</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">3</span><span class="p">);</span>
<span class="kd">const</span> <span class="nx">repos</span> <span class="o">=</span> <span class="p">[];</span>
<span class="kd">let</span> <span class="nx">remainingCount</span> <span class="o">=</span> <span class="nx">events</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span>
<span class="nx">events</span><span class="p">.</span><span class="nx">forEach</span><span class="p">(</span><span class="nx">event</span> <span class="o">=></span> <span class="p">{</span>
<span class="nx">fetchRepo</span><span class="p">(</span><span class="nx">event</span><span class="p">.</span><span class="nx">repo</span><span class="p">.</span><span class="nx">name</span><span class="p">,</span> <span class="p">(</span><span class="nx">err</span><span class="p">,</span> <span class="nx">data</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">err</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="nx">callback</span><span class="p">(</span><span class="nx">err</span><span class="p">);</span>
<span class="p">}</span>
<span class="nx">repos</span><span class="p">.</span><span class="nx">push</span><span class="p">({</span>
<span class="na">author</span><span class="p">:</span> <span class="nx">data</span><span class="p">.</span><span class="nx">owner</span><span class="p">.</span><span class="nx">login</span><span class="p">,</span>
<span class="na">avatar</span><span class="p">:</span> <span class="nx">data</span><span class="p">.</span><span class="nx">owner</span><span class="p">.</span><span class="nx">avatar_url</span><span class="p">,</span>
<span class="na">name</span><span class="p">:</span> <span class="nx">data</span><span class="p">.</span><span class="nx">name</span><span class="p">,</span>
<span class="na">full_name</span><span class="p">:</span> <span class="nx">data</span><span class="p">.</span><span class="nx">full_name</span><span class="p">,</span>
<span class="na">url</span><span class="p">:</span> <span class="nx">data</span><span class="p">.</span><span class="nx">html_url</span><span class="p">,</span>
<span class="na">description</span><span class="p">:</span> <span class="nx">data</span><span class="p">.</span><span class="nx">description</span>
<span class="p">});</span>
<span class="nx">remainingCount</span> <span class="o">-=</span> <span class="mi">1</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">remainingCount</span> <span class="o"><=</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">clearTimeout</span><span class="p">(</span><span class="nx">timeout</span><span class="p">);</span>
<span class="nx">callback</span><span class="p">(</span><span class="kc">null</span><span class="p">,</span> <span class="nx">repos</span><span class="p">)</span>
<span class="p">}</span>
<span class="p">});</span>
<span class="p">});</span>
<span class="p">});</span>
<span class="p">};</span>
</code></pre></div>
<p>That makes me feel a bit better. A small win, but the asynchronous patterns are
still the same, as is the nesting level. Well until we think of something,
let’s just consider breaking our problem down into smaller logical chunks.</p>
<h2>Encapsulating Logic</h2>
<p>Let’s start by separating the idea of fetching a user from the concept of
making 3 additional requests for the individual repositories. I won’t cover how
the iteration works in this post, but will cover that bit more in the next.</p>
<p>I think our best place to separate this code out into a new function is right
after where the events are sliced into a subset of the collection. However, I
am blocked by one thing:</p>
<div class="highlight"><pre class="highlight javascript"><code><span class="nx">clearTimeout</span><span class="p">(</span><span class="nx">timeout</span><span class="p">);</span>
</code></pre></div>
<p>In that line I’m trying to clear out the timeout we set at the top of the
<code>fetchReposForLatestActivity</code> function. We do this in case any of the HTTP
requests take too long, error out, or our counter never reaches 0. Looking
closely, this also includes the <code>fetchEventsForUser</code> request.</p>
<p>This could be a blocker because I don’t want to need to keep <code>timeout</code> from the
lexical scope of the parent function. Thankfully, I don’t notice any reason
this timeout <em>needs</em> to be cleared at the end of particular requests, just that
it needs to be cleared if all requests complete successfully. In fact…I think
there is an error here. We want the timeout to be cleared on failure too!
Cleaning up old crufty code can be a great way to uncover bugs. Well we can
address that in a bit - one step at a time when refactoring.</p>
<p>Back on topic, let’s yank all is code into yet another asynchronous function
and invoke it from the same place.</p>
<div class="highlight"><pre class="highlight javascript"><code><span class="kd">const</span> <span class="nx">fetchReposForEvents</span> <span class="o">=</span> <span class="p">(</span><span class="nx">events</span><span class="p">,</span> <span class="nx">callback</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span>
<span class="kd">const</span> <span class="nx">repos</span> <span class="o">=</span> <span class="p">[];</span>
<span class="kd">let</span> <span class="nx">remainingCount</span> <span class="o">=</span> <span class="nx">events</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span>
<span class="nx">events</span><span class="p">.</span><span class="nx">forEach</span><span class="p">(</span><span class="nx">event</span> <span class="o">=></span> <span class="p">{</span>
<span class="nx">fetchRepo</span><span class="p">(</span><span class="nx">event</span><span class="p">.</span><span class="nx">repo</span><span class="p">.</span><span class="nx">name</span><span class="p">,</span> <span class="p">(</span><span class="nx">err</span><span class="p">,</span> <span class="nx">data</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">err</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="nx">callback</span><span class="p">(</span><span class="nx">err</span><span class="p">);</span>
<span class="p">}</span>
<span class="nx">repos</span><span class="p">.</span><span class="nx">push</span><span class="p">({</span>
<span class="na">author</span><span class="p">:</span> <span class="nx">data</span><span class="p">.</span><span class="nx">owner</span><span class="p">.</span><span class="nx">login</span><span class="p">,</span>
<span class="na">avatar</span><span class="p">:</span> <span class="nx">data</span><span class="p">.</span><span class="nx">owner</span><span class="p">.</span><span class="nx">avatar_url</span><span class="p">,</span>
<span class="na">name</span><span class="p">:</span> <span class="nx">data</span><span class="p">.</span><span class="nx">name</span><span class="p">,</span>
<span class="na">full_name</span><span class="p">:</span> <span class="nx">data</span><span class="p">.</span><span class="nx">full_name</span><span class="p">,</span>
<span class="na">url</span><span class="p">:</span> <span class="nx">data</span><span class="p">.</span><span class="nx">html_url</span><span class="p">,</span>
<span class="na">description</span><span class="p">:</span> <span class="nx">data</span><span class="p">.</span><span class="nx">description</span>
<span class="p">});</span>
<span class="nx">remainingCount</span> <span class="o">-=</span> <span class="mi">1</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">remainingCount</span> <span class="o"><=</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">callback</span><span class="p">(</span><span class="kc">null</span><span class="p">,</span> <span class="nx">repos</span><span class="p">)</span>
<span class="p">}</span>
<span class="p">});</span>
<span class="p">});</span>
<span class="p">};</span>
<span class="kd">const</span> <span class="nx">fetchReposForLatestActivity</span> <span class="o">=</span> <span class="p">(</span><span class="nx">user</span><span class="p">,</span> <span class="nx">callback</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span>
<span class="kd">let</span> <span class="nx">timeout</span> <span class="o">=</span> <span class="nx">setTimeout</span><span class="p">(</span><span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
<span class="nx">callback</span><span class="p">(</span><span class="k">new</span> <span class="nb">Error</span><span class="p">(</span><span class="dl">'</span><span class="s1">Timed out</span><span class="dl">'</span><span class="p">));</span>
<span class="p">},</span> <span class="mi">3000</span><span class="p">);</span>
<span class="nx">fetchEventsForUser</span><span class="p">(</span><span class="nx">user</span><span class="p">,</span> <span class="p">(</span><span class="nx">err</span><span class="p">,</span> <span class="nx">allEvents</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">err</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="nx">callback</span><span class="p">(</span><span class="nx">err</span><span class="p">);</span>
<span class="p">}</span>
<span class="nx">fetchReposForEvents</span><span class="p">(</span><span class="nx">allEvents</span><span class="p">.</span><span class="nx">slice</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">3</span><span class="p">),</span> <span class="p">(</span><span class="nx">err</span><span class="p">,</span> <span class="nx">repos</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">err</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="nx">callback</span><span class="p">(</span><span class="nx">err</span><span class="p">);</span>
<span class="p">}</span>
<span class="nx">clearTimeout</span><span class="p">(</span><span class="nx">timeout</span><span class="p">);</span>
<span class="nx">callback</span><span class="p">(</span><span class="kc">null</span><span class="p">,</span> <span class="nx">repos</span><span class="p">);</span>
<span class="p">});</span>
<span class="p">});</span>
<span class="p">};</span>
</code></pre></div>
<p>I like this a lot better for a few reasons:</p>
<ol>
<li>I don’t have to care about how events are iterated over inside of the
<code>fetchReposForLatestActivity</code> function anymore - I’ve decoupled the concept.
Instead, now it is the responsibility of <code>fetchReposForEvents</code> to care about
the iteration over the multiple HTTP requests, and how repos are trimmed
down.</li>
<li>It shortens up the body of <code>fetchReposForLatestActivity</code> into a nice
consumable chunk. I can see two main error cases right up front, see when
the timeout gets cleared, and what gets sent back to the callback.</li>
<li>That bug we found regarding the <code>timeout</code> not being cleared when errors
occur does not need to interfere with the <code>fetchReposForEvents</code> inner
workings, it will just deal with errors or success inside of the callback it
fires upon completion.</li>
</ol>
<p>So did we lessen the nesting level? Technically we did, since the iteration is
no longer within this function, but the callback nesting is still the same.</p>
<p>This wouldn’t inherently be a problem in a real codebase, but I’m trying to
teach you something, so this simply will not do.</p>
<p>We’ll start looking at some new techniques soon for flatting out our callbacks
soon, but in the next post I think it’d be a good idea to explain how waiting
for multiple callbacks to complete were handled in this app.</p>
<p>You can get a before and after comparison of this as a <a href="https://gist.github.com/machuga/e0dae53637be1ed6b3a97923cfadc775">gist
here</a>.</p>
Grokkable Concurrency in JavaScripthttp://matthewmachuga.com/blog/2019/grokkable-concurrency-in-javascript.html2019-02-03T19:30:00+00:002023-11-10T13:34:59+00:00Matt Machuga<p><strong>NOTE:</strong> This is the first post in a series on Concurrent Programming in JavaScript.</p>
<h2>Introduction to the Problem</h2>
<p><a href="http://callbackhell.com/">Callback Hell</a> is something you’ll hear many JavaScript developers refer to, and not endearingly. It is a very real place, and is to be feared, but it is fortunately something that can be avoided with a number of tactics. We will be reviewing a prime example of Callback Hell code to study and begin understanding its weaknesses so that we can begin to learn ways to clean it up. The logical place to starts seems to be with focusing solely on callbacks, but there is so much more to learn!</p>
<h2>Problems in the Inferno</h2>
<div class="highlight"><pre class="highlight javascript"><code><span class="kd">const</span> <span class="kd">get</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="dl">'</span><span class="s1">./get</span><span class="dl">'</span><span class="p">);</span> <span class="c1">// get(url, callback)</span>
<span class="kd">const</span> <span class="nx">githubApi</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">https://api.github.com</span><span class="dl">'</span><span class="p">;</span>
<span class="kd">const</span> <span class="nx">githubEventsUrlFor</span> <span class="o">=</span> <span class="nx">username</span> <span class="o">=></span> <span class="s2">`</span><span class="p">${</span><span class="nx">githubApi</span><span class="p">}</span><span class="s2">/users/</span><span class="p">${</span><span class="nx">username</span><span class="p">}</span><span class="s2">/events`</span><span class="p">;</span>
<span class="kd">const</span> <span class="nx">githubRepoUrlFor</span> <span class="o">=</span> <span class="nx">repo</span> <span class="o">=></span> <span class="s2">`</span><span class="p">${</span><span class="nx">githubApi</span><span class="p">}</span><span class="s2">/repos/</span><span class="p">${</span><span class="nx">repo</span><span class="p">}</span><span class="s2">`</span><span class="p">;</span>
<span class="kd">const</span> <span class="nx">fetchReposForLatestActivity</span> <span class="o">=</span> <span class="p">(</span><span class="nx">user</span><span class="p">,</span> <span class="nx">callback</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span>
<span class="kd">let</span> <span class="nx">timeout</span> <span class="o">=</span> <span class="nx">setTimeout</span><span class="p">(</span><span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
<span class="nx">callback</span><span class="p">(</span><span class="k">new</span> <span class="nb">Error</span><span class="p">(</span><span class="dl">'</span><span class="s1">Timed out</span><span class="dl">'</span><span class="p">));</span>
<span class="p">},</span> <span class="mi">3000</span><span class="p">);</span>
<span class="kd">get</span><span class="p">(</span><span class="nx">githubEventsUrlFor</span><span class="p">(</span><span class="nx">user</span><span class="p">),</span> <span class="p">(</span><span class="nx">err</span><span class="p">,</span> <span class="nx">allEvents</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">err</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="nx">callback</span><span class="p">(</span><span class="nx">err</span><span class="p">);</span>
<span class="p">}</span>
<span class="kd">const</span> <span class="nx">events</span> <span class="o">=</span> <span class="nx">allEvents</span><span class="p">.</span><span class="nx">slice</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">3</span><span class="p">);</span>
<span class="kd">const</span> <span class="nx">repos</span> <span class="o">=</span> <span class="p">[];</span>
<span class="kd">let</span> <span class="nx">remainingCount</span> <span class="o">=</span> <span class="nx">events</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span>
<span class="nx">events</span><span class="p">.</span><span class="nx">forEach</span><span class="p">(</span><span class="nx">event</span> <span class="o">=></span> <span class="p">{</span>
<span class="kd">get</span><span class="p">(</span><span class="nx">githubRepoUrlFor</span><span class="p">(</span><span class="nx">event</span><span class="p">.</span><span class="nx">repo</span><span class="p">.</span><span class="nx">name</span><span class="p">),</span> <span class="p">(</span><span class="nx">err</span><span class="p">,</span> <span class="nx">data</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">err</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="nx">callback</span><span class="p">(</span><span class="nx">err</span><span class="p">);</span>
<span class="p">}</span>
<span class="nx">repos</span><span class="p">.</span><span class="nx">push</span><span class="p">({</span>
<span class="na">author</span><span class="p">:</span> <span class="nx">data</span><span class="p">.</span><span class="nx">owner</span><span class="p">.</span><span class="nx">login</span><span class="p">,</span>
<span class="na">avatar</span><span class="p">:</span> <span class="nx">data</span><span class="p">.</span><span class="nx">owner</span><span class="p">.</span><span class="nx">avatar_url</span><span class="p">,</span>
<span class="na">name</span><span class="p">:</span> <span class="nx">data</span><span class="p">.</span><span class="nx">name</span><span class="p">,</span>
<span class="na">full_name</span><span class="p">:</span> <span class="nx">data</span><span class="p">.</span><span class="nx">full_name</span><span class="p">,</span>
<span class="na">url</span><span class="p">:</span> <span class="nx">data</span><span class="p">.</span><span class="nx">html_url</span><span class="p">,</span>
<span class="na">description</span><span class="p">:</span> <span class="nx">data</span><span class="p">.</span><span class="nx">description</span>
<span class="p">});</span>
<span class="nx">remainingCount</span> <span class="o">-=</span> <span class="mi">1</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">remainingCount</span> <span class="o"><=</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">clearTimeout</span><span class="p">(</span><span class="nx">timeout</span><span class="p">);</span>
<span class="nx">callback</span><span class="p">(</span><span class="kc">null</span><span class="p">,</span> <span class="nx">repos</span><span class="p">)</span>
<span class="p">}</span>
<span class="p">});</span>
<span class="p">});</span>
<span class="p">});</span>
<span class="p">};</span>
<span class="nx">fetchReposForLatestActivity</span><span class="p">(</span><span class="dl">'</span><span class="s1">machuga</span><span class="dl">'</span><span class="p">,</span> <span class="p">(</span><span class="nx">err</span><span class="p">,</span> <span class="nx">repos</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">err</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">error</span><span class="p">(</span><span class="nx">err</span><span class="p">);</span>
<span class="k">return</span><span class="p">;</span>
<span class="p">}</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">repos</span><span class="p">);</span>
<span class="p">});</span>
</code></pre></div>
<p>The above figure is an example of some code that starts pushing out to the right pretty quickly. What do I mean by pushing to the right?</p>
<h2>Nesting</h2>
<p>Look above at how the code starts indenting further and further to the right depending on which level of callback nesting we’re at. At the deepest point, we are 3 callbacks deep, and there is even a bit of iteration involved to push it out further - which adds its own extra level of complexity we’ll address in a moment. To be clear, it is not necessarily the number of spaces (that’s right, not tabs, internet) from the left margin that cause conflict; though harder to read, the biggest issue it causes is nested context.
The most deeply nested part in our code knows about and mutates the <code>timeout</code> variable we set in the upper-most <code>fetchReposForLatestActivity</code> function, and also knows about the original callback sent into that function. Even at the current length, but doubly so if this function was longer, it’d be very easy to start losing mental context of what variable is declared where. It’s hard to remember what variables are still in scope, what you’ve accidentally changed, etc. from parent scopes. It is a very easy way to cause unexpected behavior and a good way to lose yourself in your code. Additionally, if you aren’t cautious how you nest your scopes, letting variables from higher lexical scopes be used in lower ones, it can make extracting functions a bit of a challenge later.</p>
<h2>Error Handling</h2>
<p>Explicit error handling is a good thing. Go, for example, embraces it as a first class citizen, where functions can return an error along with the intended return value. However, in JavaScript, error handling is all conventional, and thus sometimes things can surprise you. For instance, with traditional NodeJS style error handling (used in this figure), when errors are thrown from a function, the error should be sent as the first argument of the callback. Another style that pops up is the <code>errback</code>, where there is a second, separate callback to handle the error case, and the success callback does not receive an error argument.
Example:</p>
<div class="highlight"><pre class="highlight javascript"><code><span class="kd">function</span> <span class="nx">doAThing</span><span class="p">(</span><span class="nx">errback</span><span class="p">,</span> <span class="nx">callback</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span><span class="p">(</span><span class="nx">wrongThingHappens</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="nx">errback</span><span class="p">(</span><span class="k">new</span> <span class="nb">Error</span><span class="p">(</span><span class="dl">'</span><span class="s1">oops</span><span class="dl">'</span><span class="p">));</span>
<span class="p">}</span>
<span class="nx">callback</span><span class="p">(</span><span class="dl">'</span><span class="s1">success</span><span class="dl">'</span><span class="p">);</span>
<span class="p">}</span>
<span class="nx">doAThing</span><span class="p">(</span><span class="nx">console</span><span class="p">.</span><span class="nx">error</span><span class="p">,</span> <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">)</span>
</code></pre></div>
<p>There are other libraries that will, intentionally or unintentionally, throw the error in a destructive way (not sending it to the callback) if the error is thrown synchronously. This is a great way to cause unexpected behavior, and has caused me some grief over the years. This is definitely an area where consistency can help.</p>
<h2>Only-Once</h2>
<p>Let’s take a look at how we call our <code>fetchReposForLatestActivity</code> function:</p>
<div class="highlight"><pre class="highlight javascript"><code><span class="nx">fetchReposForLatestActivity</span><span class="p">(</span><span class="dl">'</span><span class="s1">machuga</span><span class="dl">'</span><span class="p">,</span> <span class="p">(</span><span class="nx">err</span><span class="p">,</span> <span class="nx">repos</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">err</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">error</span><span class="p">(</span><span class="nx">err</span><span class="p">);</span>
<span class="k">return</span><span class="p">;</span>
<span class="p">}</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">repos</span><span class="p">);</span>
<span class="p">});</span>
</code></pre></div>
<p>Despite the size of the underlying function and numerous HTTP calls it protects us from worrying about, it is a pretty simple function. We pass it a <code>username</code> and a callback, and it will either send us an error or a list of repositories back. Great! Now what if we want to cache those repositories for a bit to avoid needing to make extraneous calls over the network? I have seen this done in so many terrifying ways (and done a few myself when I started writing JS) that I will not enumerate in this post, but the gist of it: If you are using timeouts or setting a cache value in a higher scope without ensuring you have something like a lock to prevent updating a variable multiple times, you are probably on the wrong path. Even our iteration over repos in the above examples isn’t perfect.</p>
<p>This can introduce challenges for structuring code because if you want to have any other code that uses the list of repos, they must be called from within the above callback to have the <code>repos</code> variable in scope. This comes right back to nesting. The solutions to these problems aren’t hard, they just take a shift in thinking if you’ve only done synchronous programming up until this point.</p>
<h2>Iteration with Callbacks</h2>
<p>Here be dragons. Let’s take a look at a shortened version of our iteration above:</p>
<div class="highlight"><pre class="highlight javascript"><code><span class="kd">const</span> <span class="nx">repos</span> <span class="o">=</span> <span class="p">[];</span>
<span class="kd">let</span> <span class="nx">remainingCount</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="nx">events</span><span class="p">.</span><span class="nx">forEach</span><span class="p">(</span><span class="nx">event</span> <span class="o">=></span> <span class="p">{</span>
<span class="kd">get</span><span class="p">(</span><span class="nx">githubRepoUrlFor</span><span class="p">(</span><span class="nx">event</span><span class="p">.</span><span class="nx">repo</span><span class="p">.</span><span class="nx">name</span><span class="p">),</span> <span class="p">(</span><span class="nx">err</span><span class="p">,</span> <span class="nx">data</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">err</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="nx">callback</span><span class="p">(</span><span class="nx">err</span><span class="p">);</span>
<span class="p">}</span>
<span class="nx">repos</span><span class="p">.</span><span class="nx">push</span><span class="p">(...);</span>
<span class="nx">remainingCount</span> <span class="o">-=</span> <span class="mi">1</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">remainingCount</span> <span class="o"><=</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">clearTimeout</span><span class="p">(</span><span class="nx">timeout</span><span class="p">);</span>
<span class="nx">callback</span><span class="p">(</span><span class="kc">null</span><span class="p">,</span> <span class="nx">repos</span><span class="p">)</span>
<span class="p">}</span>
<span class="p">});</span>
<span class="p">});</span>
</code></pre></div>
<p>What we do is set a variable, <code>remainingCount</code> to be equal to the length of the array we are using. In our case, we have 3 events. Then every time a callback from <code>get</code> gets executed we decrement the value of <code>remainingCount</code> by one, and then when <code>remainingCount</code> becomes <code>0</code>, we know all <code>get</code> requests have completed and can execute the callback passed into our <code>fetchReposForLatestActivity</code> function. We also clear the timeout set earlier in the function so that if any HTTP requests get stuck we can still abort the <code>fetchReposForLatestActivity</code> function. If any HTTP requests come back with an error, then we have chosen to fail immediately and call <code>callback</code> with the error we received. It should be noted that I did not handle any actual clean up of cancelling HTTP requests and other such things for brevity.</p>
<h2>Cleaning up the Code</h2>
<p>How can we clean up these various things? That’s what we’re going to cover over the next several blog posts - first with callbacks, then with Promises and other constructs. We’ll also go into more advanced patterns for handling common situations you’ll find yourself in when dealing with processing data, like sequential processing, concurrent processing, and more. I’d like to keep each one succinct enough to read quickly and search back through for quick references as you need them, so I will try to keep the amount of material to learn in each post limited. This will go from beginner to more advanced topics fairly quickly.</p>
<p>If you want to keep up to date with updates, please subscribe to my <a href="https://matthewmachuga.com">mailing list</a> or <a href="https://matthewmachuga.com/blog/feed.xml">RSS feed</a>.</p>
Loss and Meaninghttp://matthewmachuga.com/blog/2018/loss-and-meaning.html2018-04-28T00:00:00+00:002023-11-10T13:34:59+00:00Matt Machuga<p>I started writing pieces of this down a bit over a week ago, sitting alone in a
calm hospital cafeteria of an out of town. My wife was waiting on her dinner in
her room, and I was slowly and distantly chewing on my dinner.</p>
<p>At this point it had been 28 hours after learning my unborn child no longer had
a heartbeat.</p>
<h1>Our Story</h1>
<p>The day before started off so jovial. I met a new employee at work and
mentioned that I had 2 kids and my third on the way. I told her, in fact, I’d
be going to find out the sex of the baby that afternoon. Evidently our newer
doctor’s office favors anatomy scans after 20 weeks, so this was actually
fairly late for us compared to our last two girls.</p>
<p>At the appointment we got taken back nearly a half hour late and by this time
were very anxious to find out if our baby was a girl or boy. The sonograph tech
got everything set up, pressed the device against my wife’s belly, and there
was our baby — so much bigger than our last sonogram 8 weeks prior! The images
were a bit off, which I guess is normal if the bladder is full. After about a
minute the tech asked my wife to empty her bladder. My wife and I laughed hard
and she complied. As my wife went into the restroom, the tech mentioned she’d
be back in a minute and left the room. My wife came back out shortly after, we
joked around a bit more, and then after about 5 minutes started to get
impatient and frustrated.</p>
<p>We assumed that she started chatting with someone or took a smoke break. I
peeked out into the hall and could hear her talking to someone. Then my wife
wondered aloud from behind me something we hadn’t considered, “I wonder if
something’s wrong…”</p>
<p>The tech came back down the hall and was bringing a nurse or someone with
her — I can’t remember who she was at this point. When they came into the room
she introduced herself and I cut her short asking if something was wrong. The
next time she opened her mouth she broke us.</p>
<p>She told us the baby had no heartbeat.</p>
<p>My wife started bawling and I don’t remember anything else she told us until I
asked her to check again and held out hope that they were wrong. They scanned
for quite a while. I could see my baby there on the screen — arms, legs, head,
and ribs. But there was no familiar fluttering between those ribs or blood
flowing. We were told we had to leave for Pittsburgh immediately to “evaluate
our options for delivering” the baby. I made the out of town hospital check yet
again and they got three doctors to confirm before I wholly accepted what had
happened. That acceptance finally brought some tears for me.</p>
<p>Our baby. Our hopes. Our dreams. Gone.</p>
<h1>Your Story</h1>
<p>I intended to keep this largely private, and most details I will. However I
want to make some of this public because this sort of thing happens far more
often than I realized, and nothing can prepare you for the pain, sadness, and
hopelessness in that moment and days to follow learning your child is
stillborn. That being said, knowing what to face going in may help lessen the
repeated blows as they tell you what to expect and remind you what decisions
you have to make. My third child never got to see the world and leave their own
mark, so I want to ensure that their short life makes some positive impact to
honor them.</p>
<h1>Hearing the News</h1>
<p>Nothing I can say hear will lessen the hit. It fucking sucks and it will always
hurt, even when it’s just a memory. I can tell you that you and your partner
are not alone. Many people learn they’ve had a miscarriage or a stillborn and
will understand the pain you’re feeling. A surprising number of people you
already know may have experienced it and you’ve never known. I’m fortunate (as
fortunate as this sort of thing can be) in that I’ve known several people who
have experienced this. Talking through it with my oldest and dearest friend,
and hearing his experience, helped me greatly — I hope that you too have
someone close. Some people keep this close to the chest and haven’t told you
before they suffered this sort of loss; however, they may choose to open up to
you in order to help you through the process.</p>
<p>There are also many organizations and support groups both online and in person
that you can reach out to and communicate with. These can be just as invaluable
as someone in your personal network. You may even make some lifelong friends
out of this experience.</p>
<p>However you choose to do this, I cannot encourage you enough to not handle this
alone. It may feel like all you want to do, but bottling up your emotions may
prolong your grieving and pain. Please, please, talk to someone about what
you’re going through. At bare minimum, please communicate openly with your
partner.</p>
<h1>Your Partner</h1>
<p>This section is targeted primarily to men who are suffering a loss with their
partner, because I am highly under qualified to discuss this from the
perspective of a woman.</p>
<p>This time is insanely hard for both you and your partner. Our instinct seems to
be to protect our partner, but when you both suffer the loss it’s important to
accept that at some point you need to grieve as well. For me, along with the
need to protect my wife, I didn’t feel justified in grieving nearly as hard as
she did — she carried the baby inside her for 20 weeks. They were never apart,
she would always talk to the baby, everything about her was changed in some way
by the baby, and even after death, the baby was still there. I can’t fathom how
hard this was on my wife and I’ve been with her every step of the way. From
numerous accounts, articles, friends, and from my wife herself, I was reminded
that I’m experiencing the loss as well and it’s okay and healthy to acknowledge
it.</p>
<p>For the first several hours I was rather stoic and blank, trying my hardest to
comfort my wife and only trying to drive the process forward as we had to make
decisions, arrangements, and communication throughout the day. In one of the
hospital rooms my wife waiting for scans my wife and I were trying to research
how we could try to break the news to our daughters that this happened, and I
saw something mentioning that as the father I shouldn’t be afraid to show my
emotions, and not doing so may signal to my wife that I don’t care.</p>
<p>I immediately asked my wife if I’ve come off as indifferent throughout the day,
not wanting to add to her pain if it was the case. My wife and I have been
married for nearly 6 years and together for over 15, so she assured me that she
knew I cared and knows how I get when situations go sideways. She did, however,
affirm that I can’t bottle my emotions up and that she’s not that only one that
suffered a loss. She told me to let myself grieve an not only be focused on
her. When I finally shed some tears after another interaction with the doctors,
she was there for me as I was for her — holding me tightly. It made her feel a
bit better knowing that she could help comfort me in the situation.</p>
<h1>Telling Others</h1>
<p>Adding to the pain of the situation is the fact that people may know you were
expecting a baby, but don’t know the baby is gone. This information is yours,
but unfortunately if people aren’t informed you’ll be hearing the questions
“How are along are you?”, “When is the baby due?”, “Is it a boy or girl” and
reliving it every time. We handled it by informing those closest to us and
letting them spread the news. For neighbors and friends I make sure I’m the one
they run into first so that I can give them the heads up so my wife doesn’t get
put into the situation.</p>
<p>Outside of word-of-mouth, you may choose to notify multiple people at once via
Facebook or similar social networks (we opted not to). Or you may personally
want to tell people case-by-case. Do what feels right to you. And this brings
us to the hardest ones to tell.</p>
<h1>Telling Your Children</h1>
<p>Along with actually hearing the news about the death, telling our kids was the
hardest part. We agonized over how to tell them. Read countless articles
online, and I read some of the books on grief they gave us while my wife
napped. There are so many recommendations from different folk, but one theme
seems to be consistent: don’t sugar coat it or use confusing terms because they
will tend to take it literally. Things like “we lost the baby”, “the baby is
asleep and can’t wake up”, “the baby went to heaven”, or similar phreases imply
impermanent states. Most sources said to tell them and use real words, but
don’t disclose more than what they ask.</p>
<p>For us, our girls are 5 and almost 3. When we got home from the hospital we
told them the baby wasn’t strong enough to be born and had died. I’m not going
to go into details of reactions, but they understood what happened and largely
handled the news well. Children are insanely resilient.</p>
<p>Now, one thing I could never find was to how to tell children where the baby
physically went. I was panicking about this part because I didn’t know how to
answer it. I’m still unsure how they’ll react when we get the urn next week,
and how we’ll explain it. At the moment I think I’m going to explain that when
babies die and aren’t able to be born, they turn them into ash since their body
can’t survive. The answer to this will also greatly depend on how you handle
the next part.</p>
<p>Another thing I’ve read is to not shield them too much as they may come to
resent being left out. They suffered a loss too (assuming you told them or were
far enough to notice), and need to be able to grieve. If you do a memorial of
any sort, let them be involved. Let them make something for the baby if that’s
how they want to express themselves. It may seem hard, but it seems to really
help.</p>
<h2>Warning: These next sections have details that are not easy to read and may be upsetting. Either stop now or be ready to proceed.</h2>
<h1>How to Deliver</h1>
<p>As if mothers haven’t been through enough, they still need to get the baby and
placenta out. I’m not going to tell you how we chose to handle it, because it’s
important that you and your partner handle it either the way you want, or the
way your health care provider tells you is medically safest. I am not qualified
to give recommendations.</p>
<p>There are different options based on your situation. I can tell you they seem
very reluctant to perform a C-Section because despite it being performed
commonly, it’s a risky surgery that is often done for the sake of the safety of
the baby. Since the baby is no longer alive, they don’t want to risk the
mother. So that leaves two more common options.</p>
<h2>Vaginal Delivery</h2>
<p>A standard vaginal delivery is one of the options they’ll present as long as
there are no blocking risks. They’ll certainly offer an epidural and other
things to make the mother as comfortable as possible, but like any other option
this is not an easy process. If you’d like a chance to hold your child before
they are taken away, this is the most realistic option. Some people aren’t sure
whether they’d like to. Think hard on it and discuss it with your partner.
Decide whether this option is right for you and if the risks are worth it. This
next part is a bit gruesome, but I want you to be aware of it in case your
provider does not give you the warning. Make sure the sonography tech tells you
an estimate on how far along the baby was when it passed way. The placenta
doesn’t necessarily know the baby passed away right away, so delivering a
stillborn that passed away a day ago vs one that passed away a couple weeks
prior can be very different experiences. I know that’s not giving pleasant
imagery, and the thoughts of it were horrifying when the hospital listed
possibilities to us, but it’s important to know.</p>
<p>They will likely offer to try to get you hand prints and foot prints for a
memory box.</p>
<h2>D & E</h2>
<p>This method is common for babies that pass away prior to 20 weeks, high-risk
pregnancies, or women who have had prior C-sections. In this procedure, it is
highly unlikely that you’ll be able to hold your child because they “evacuate
the pregnancy”, implying that they will almost always need to remove everything
from the uterus in pieces. This procedure is also extremely unpleasant to hear
and imagine, but they will tell you it is the safest for the mother. While it
is a short procedure (I think they said less than a half hour), it can take as
long as labor and delivery because they need to dilate the cervix to 2–3cm over
about a day and secure an operating room for the procedure.</p>
<p>They will still offer you a memory box with handprints and footprints, and will
try hard to make it possible, but they caveat it with the fact that it may not
be possible to get the prints due to the way the procedure is done.</p>
<h1>Autopsy</h1>
<p>This part is at least as hard to stomach as the decision on delivery. Often
times the doctors have no idea why the baby passed away. They will take blood
from the mother and tissue from the pregnancy to do some testing, but those are
still not as conclusive as an autopsy. An autopsy will allow them to try to see
what may have happened in two different ways. They can do an external autopsy,
in which they will not harm the body (from what I can remember, I recommend
searching the web to confirm or asking your physician), but will take samples
that they can test further. This yields more information, but is still not as
informative as an internal autopsy. This is exactly what you think it is, more
or less like what you’ve seen on TV. They will cut into the body and examine
each organ in ways I don’t want to think about too much. It’s hard to picture,
but this is your best chance at finding out what happened to your baby.</p>
<p>If you’re planning on having another baby, this kind of information can be
helpful to understand your chances of it happening again or what you can do to
prevent it (if anything). It can also be helpful in knowing if there is
anything hereditary that you need to be concerned about with your existing or
future children. The autopsy also helps research in discovering why some of
these things happen, and what people and doctors can do to prevent them in the
future.</p>
<p>You need to choose what is right for you. It’s a hard choice with tradeoffs,
and there’s no getting around it.</p>
<h1>Disposal</h1>
<p>I’m sorry, that term sounds insensitive, but it is unfortunately the term that
will be used. From what I’ve read and what doctors told us (within Pennsylvania
at least), babies in the womb for less than 20 weeks have to be disposed of by
the hospital per regulation. From what I understand, the remains will be
cremated, but it will be done with others remain and buried together at a
cemetery. Evidently babies will be buried in a specified area at many
cemeteries. There will be no grave to visit in this situation. Above 20 weeks
you can choose to allow the hospital to dispose of the remains or you can
dispose of it. For fairly obvious reasons, if they perform a D & E they will
only allow you to have the remains cremated to avoid further trauma. If you
have a vaginal delivery you can decide whether to have a burial or cremation
(which you can choose to inter later).</p>
<p>You’ll need select a funeral home to handle the remains. They will continually
ask you if you’ve decided on one — be sure to research and find one that will
work with you for your needs. Many will offer a heavy discount for stillborns
and deceased infants. The one we dealt with were incredibly kind, worked with
us, and gave us a deep discount. Usually the hospital will send in a social
worker to help you find a funeral home and tell you ones they partner with or
are known to offer discounts. If you need help affording the costs, there are
organizations like <a href="http://emmasfootprints.com/">Emma’s Footprints</a> that are
available to help you.</p>
<h1>Conclusion</h1>
<p>I sincerely hope you never have to deal with this sort of loss. Losing a baby
is hard no matter whether it’s an early miscarriage, half way through, or any
further along. It’s an odd feeling grieving a child you’ve never seen, but that
child is yours no matter what. You had hopes and dreams for that baby. You’ve
undoubtedly pictured what life would be like, what their life would be like as
they got older. You’ve thought about how he or she would play with their
siblings as they grew up together. Take the time you need to mourn your loss
the way you need to. The choices aren’t easy, especially given the pain you’ll
be in, but those decisions stay with you. Think as carefully as you can and do
what you think will be right for you and your family. My child had its life cut
short, but I’m hoping this article written based on that short life and death
will help you and others understand what is to come.</p>
<p>I wish you all the best, and remember — you are not alone.</p>
Taking a Step Back & Scratching an Itchhttp://matthewmachuga.com/blog/2017/taking-a-step-back-scratching-an-itch.html2017-08-14T00:00:00+00:002023-11-10T13:34:59+00:00Matt Machuga<p>I’ve been spending the past two weeks adjusting to working at Auth0. Thus far
everything’s been great. The domain is interesting and challenging, the
problems are fun, and there are a <strong>lot</strong> of smart people working here. While I’ve
been getting up to speed, I’ve been working on a new bit of functionality and
learning a few of our products. The one that’s been getting a lot of my time
this week is our <a href="https://webtask.io">Webtask.io</a> platform.</p>
<p>The elevator pitch for <a href="https://webtask.io">Webtask.io</a> is that it allows you
to make serverless HTTP endpoints with Node. It’s a pretty neat concept,
similar to AWS Lamdbda or Google Cloud Functions. One thing that we do is allow
you to require a number of modules from npm without worrying about bundling
them yourself. For determining what packages are available, I’ve been utilizing
a solution developed by one of my coworkers, <a href="https://twitter.com/tehsis">Pablo
Terradillos</a>, hosted at
<a href="https://tehsis.github.io/webtaskio-canirequire/">canirequire</a>. <code>canirequire</code>
lets anyone search for their favorite npm module to see if it’s already
available inside of a Webtask script. It’s been really handy and appreciated.</p>
<p>Over the weekend I was trying to get a little bit further on my task at work,
when I realized I need to just take a step back and solve a different problem
for a while. My mind immediately went to converting canirequire to a CLI script
so that I could search for packages without leaving my terminal. After about 30
minutes of tinkering around, since Pablo had already taken care of any of the
challenging bits, I was able to publish
<a href="https://www.npmjs.com/package/canirequire">canirequire-cli</a>. All it really does it
call the webtask endpoint that tells me what packages we support, transform the
data a bit, and then run a regex search over the modules to see if any match
what I’m looking for. Once the search is done it simply returns a JSON response
and ends.</p>
<p>The problem wasn’t hard at all, but it was enough to redirect my mind elsewhere
and scratch my own itch.</p>
<p>If you want to put some code up on Webtask.io, give the package a try:</p>
<div class="highlight"><pre class="highlight plaintext"><code>$ npm install -g canirequire-cli
$ canirequire request
{
"request": [
"2.67.0",
"2.55.0",
"2.56.0",
"2.81.0",
"2.27.0"
],
"request-progress": [
"0.3.1"
],
"request-promise": [
"1.0.2"
],
"request-replay": [
"0.3.0"
],
"xmlhttprequest": [
"1.7.0"
]
}
</code></pre></div>