<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Kasper Moskwiak</title>
    <description>The latest articles on Forem by Kasper Moskwiak (@kmoskwiak).</description>
    <link>https://forem.com/kmoskwiak</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F185855%2F35896efa-2d29-4eb6-89d9-5da0c39230c8.jpeg</url>
      <title>Forem: Kasper Moskwiak</title>
      <link>https://forem.com/kmoskwiak</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/kmoskwiak"/>
    <language>en</language>
    <item>
      <title>My approach to SSR and useEffect - discussion</title>
      <dc:creator>Kasper Moskwiak</dc:creator>
      <pubDate>Sun, 10 May 2020 22:00:26 +0000</pubDate>
      <link>https://forem.com/kmoskwiak/my-approach-to-ssr-and-useeffect-discussion-k44</link>
      <guid>https://forem.com/kmoskwiak/my-approach-to-ssr-and-useeffect-discussion-k44</guid>
      <description>&lt;p&gt;For the last few days, I was developing my personal website. I felt it needed some refreshment and as always it is a great occasion to play with something new. I've decided it will be written in React with SSR. &lt;/p&gt;

&lt;p&gt;I've put all data fetching in &lt;code&gt;useEffect&lt;/code&gt; hook - pretty standard approach. However, &lt;code&gt;useEffect&lt;/code&gt; does not play very well with server-side rendering. I've managed to work this out by creating custom hook &lt;code&gt;useSSE&lt;/code&gt; - "use server-side effect" and I've created an npm package from it.&lt;/p&gt;

&lt;p&gt;I am very curious about your opinion. Here is the package on &lt;a href="https://www.npmjs.com/package/use-sse"&gt;npm&lt;/a&gt; and GitHub repo: &lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--i3JOwpme--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/github-logo-ba8488d21cd8ee1fee097b8410db9deaa41d0ca30b004c0c63de0a479114156f.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/kmoskwiak"&gt;
        kmoskwiak
      &lt;/a&gt; / &lt;a href="https://github.com/kmoskwiak/useSSE"&gt;
        useSSE
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      use Server-Side Effect ✨in React SSR app
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;br&gt;
And here is an example on &lt;a href="https://codesandbox.io/s/falling-waterfall-wnlwc?file=/README.md"&gt;CodeSandbox&lt;/a&gt;.
&lt;h2&gt;
  
  
  And this is how it works...
&lt;/h2&gt;

&lt;p&gt;Instead of using &lt;code&gt;useEffect&lt;/code&gt; for data fetching, I use &lt;code&gt;useSSE&lt;/code&gt;. It looks like a combination of &lt;code&gt;useState&lt;/code&gt; and &lt;code&gt;useEffect&lt;/code&gt;. Here is an example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;MyComponent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useSSE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;{},&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;my_article&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http://articles-api.example.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;[]&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;useSSE&lt;/code&gt; takes 4 arguments:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;an initial state (like in &lt;code&gt;useState&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;a unique key - a global store will be created, and data will be kept under this key,&lt;/li&gt;
&lt;li&gt;effect function returning promise which resolves to data,&lt;/li&gt;
&lt;li&gt;array of dependencies (like in &lt;code&gt;useEffect&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The essence of this approach is to render application &lt;strong&gt;twice&lt;/strong&gt; on server. During first render all effect functions used in &lt;code&gt;useSSE&lt;/code&gt; hook will be registered and executed. Then server waits for all effects to finish and renders the application for the second time. However, this time all data will be available in global context. &lt;code&gt;useSSE&lt;/code&gt; will take it from context and return in &lt;code&gt;[data]&lt;/code&gt; variable.&lt;/p&gt;

&lt;p&gt;This is how it looks on server-side. The code below shows a part of &lt;code&gt;expressjs&lt;/code&gt; app where the request is handled.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Create context&lt;/span&gt;
  &lt;span class="c1"&gt;// ServerDataContext is a context provider component&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ServerDataContext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;resolveData&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;createServerContext&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="c1"&gt;// Render application for the first time&lt;/span&gt;
  &lt;span class="c1"&gt;// renderToString is part of react-dom/server&lt;/span&gt;
    &lt;span class="nx"&gt;renderToString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ServerDataContext&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; 
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;App&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/ServerDataContext&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// Wait for all effects to resolve&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;resolveData&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="c1"&gt;// My HTML is splited in 3 parts&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pagePart&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

  &lt;span class="c1"&gt;// This will put &amp;lt;script&amp;gt; tag with global variable containing all fetched data&lt;/span&gt;
  &lt;span class="c1"&gt;// This is necessary for the hydrate phase on client side&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toHtml&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pagePart&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

  &lt;span class="c1"&gt;// Render application for the second time. &lt;/span&gt;
  &lt;span class="c1"&gt;// This time take the html and stream it to browser&lt;/span&gt;
  &lt;span class="c1"&gt;// renderToNodeStream is part of react-dom/server&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;htmlStream&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;renderToNodeStream&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ServerDataContext&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;App&lt;/span&gt;&lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/ServerDataContext&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nx"&gt;htmlStream&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;end&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="nx"&gt;htmlStream&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;end&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pagePart&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
        &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;end&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On client-side application must be wrapped in provider as well. A custom context provider is prepared for this job. It will read data from global variable (it was injected by this part of code: &lt;code&gt;res.write(data.toHtml())&lt;/code&gt;).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;BroswerDataContext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;createBroswerContext&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nx"&gt;hydrate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;BroswerDataContext&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;App&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/BroswerDataContext&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;,
&lt;/span&gt;    &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;app&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it! What do you think about this approach? Is &lt;code&gt;useSSE&lt;/code&gt; something you would use in your project?&lt;/p&gt;

&lt;p&gt;Here are all resources:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt; &lt;a href="https://www.npmjs.com/package/use-sse"&gt;package on npm&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt; &lt;a href="https://github.com/kmoskwiak/useSSE"&gt;project on GitHub&lt;/a&gt;. &lt;/li&gt;
&lt;li&gt;And  an example on &lt;a href="https://codesandbox.io/s/falling-waterfall-wnlwc?file=/README.md"&gt;CodeSandbox&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>react</category>
      <category>ssr</category>
      <category>useeffect</category>
      <category>discuss</category>
    </item>
    <item>
      <title>Async iterators in JS - database iteration in NodeJS</title>
      <dc:creator>Kasper Moskwiak</dc:creator>
      <pubDate>Mon, 24 Feb 2020 20:11:22 +0000</pubDate>
      <link>https://forem.com/kmoskwiak/async-iterators-in-js-database-iteration-in-nodejs-3pm9</link>
      <guid>https://forem.com/kmoskwiak/async-iterators-in-js-database-iteration-in-nodejs-3pm9</guid>
      <description>&lt;p&gt;In this article I will give a quick example how to process entire database (let it be MongoDB, Elasticsearch or RDBS like PostgreSQL) using modern JavaScript tools. We will combine async/await, iterators and function generator in a simple yet powerful pattern which can be used in many cases.&lt;/p&gt;

&lt;p&gt;See working example on &lt;a href="https://runkit.com/kmoskwiak/5e07544f761b77001b44c45f" rel="noopener noreferrer"&gt;Runkit&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem
&lt;/h2&gt;

&lt;p&gt;Our case is to process entire database (table in RDB, collection in Mongo) entry by entry. &lt;/p&gt;

&lt;p&gt;The  easiest way would be to select all documents, put them into runtime memory and do all operations. However that’s not the answer, especially when the dataset is large and our memory limited.&lt;/p&gt;

&lt;h3&gt;
  
  
  Classic approach: limit and offset
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fif6u4t8c5m2iuylul2uw.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fif6u4t8c5m2iuylul2uw.gif" alt="Limit and offset"&gt;&lt;/a&gt;&lt;br&gt;
There is an option to use &lt;code&gt;limit&lt;/code&gt; combined with &lt;code&gt;offset&lt;/code&gt; in SQL:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;my_table&lt;/span&gt; &lt;span class="k"&gt;LIMIT&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt; &lt;span class="k"&gt;OFFSET&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;which in Mongo would look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;my_collection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;({}).&lt;/span&gt;&lt;span class="nf"&gt;skip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that in most databases the performance of this technique changes based on offset value. The bigger the offset is the slower the query will become. This is because in most cases database will process all skipped entries before returning those which interest us. Due to this obstacle some databases specify maximum value of offset, so it may not be possible to process entire database without some extra tweaking with database settings.&lt;/p&gt;

&lt;h3&gt;
  
  
  Stateful cursors
&lt;/h3&gt;

&lt;p&gt;We could take advantage of stateful technique using &lt;code&gt;cursors&lt;/code&gt;.  Cursor is an object created by database and kept in its memory. It remembers context of a query, e.g. current state of pagination. Usually we have to create cursor and then use some reference to it in further queries.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Flrmoyika0figsm8i7iuc.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Flrmoyika0figsm8i7iuc.gif" alt="Cursors"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Note that in some databases cursor has its lifetime. For example in Elasticsearch we can specify expiry time for search context in &lt;code&gt;scroll&lt;/code&gt; parameter. &lt;/p&gt;

&lt;p&gt;You may also come across limitation of maximum amount of simultaneously opened cursors.&lt;/p&gt;

&lt;h2&gt;
  
  
  An alternative: range query
&lt;/h2&gt;

&lt;p&gt;Next technique - range query - has couple of interesting features.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It is &lt;strong&gt;stateless&lt;/strong&gt;. That means you do not have to care for state expiration or state synchronization between all database nodes in your network.&lt;/li&gt;
&lt;li&gt;It has &lt;strong&gt;constant and controllable memory usage&lt;/strong&gt;. That means it can be successfully used on low memory machines and its performance does not vary on dataset size or pagination progress.&lt;/li&gt;
&lt;li&gt;It is &lt;strong&gt;not database specific&lt;/strong&gt;. After all it is just an approach how to construct a query so it can be used in most databases.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Range query is very similar to combination of limit and offset. However instead of providing number of documents to be skipped we specify boundary condition which eliminates already processed documents. &lt;br&gt;
In example dataset (visualized below) documents are sorted ascending by id. Condition  &lt;code&gt;id &amp;gt; 16&lt;/code&gt;  skips 6 documents with ids: &lt;strong&gt;1&lt;/strong&gt;, &lt;strong&gt;2&lt;/strong&gt;,  &lt;strong&gt;11&lt;/strong&gt;, &lt;strong&gt;13&lt;/strong&gt;, &lt;strong&gt;14&lt;/strong&gt;, &lt;strong&gt;16&lt;/strong&gt;. Result is identical to providing offset equal 6.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fjkk0nm9vdwnlewntmg3h.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fjkk0nm9vdwnlewntmg3h.gif" alt="Range query"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Iterating over dataset in batches of size 6 comes down to 3 steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;request first 6 documents and remember id of last document (&lt;strong&gt;16&lt;/strong&gt;),&lt;/li&gt;
&lt;li&gt;request next 6 documents with condition id &amp;gt; &lt;strong&gt;16&lt;/strong&gt;, remember last id (&lt;strong&gt;35&lt;/strong&gt;),&lt;/li&gt;
&lt;li&gt;request  next 6 documents  with condition id &amp;gt; &lt;strong&gt;35&lt;/strong&gt;. Note that this time only 3 documents were returned which means it is the end of our dataset.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Things to remember:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;dataset must be &lt;strong&gt;sorted&lt;/strong&gt; by key which our condition is applied to,&lt;/li&gt;
&lt;li&gt;to achieve best performance and keep constant memory usage field used in condition should be &lt;strong&gt;indexed&lt;/strong&gt;,&lt;/li&gt;
&lt;li&gt;also values under this field  must be &lt;strong&gt;unique&lt;/strong&gt;. If not range query may “lose” some documents.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We will use range query in our example.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsatj5k01401k4mbye8g6.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsatj5k01401k4mbye8g6.gif" alt="Ooooh yeah! Can do!"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Async iteration in JavaScript
&lt;/h2&gt;

&lt;p&gt;We will be using &lt;code&gt;async-await&lt;/code&gt; combined with &lt;code&gt;functions generator&lt;/code&gt; and custom &lt;code&gt;iterator&lt;/code&gt;. &lt;br&gt;
This combination is called &lt;code&gt;async iteration&lt;/code&gt; and its proposal can be found &lt;a href="https://github.com/tc39/proposal-async-iteration" rel="noopener noreferrer"&gt;here&lt;/a&gt;.  However individual parts were in NodeJS earlier the whole combo can be used inside for loop &lt;a href="https://node.green/#ES2018-features-Asynchronous-Iterators" rel="noopener noreferrer"&gt;since version 10&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;In the end we want to be able to use for-loop to synchronously iterate over database.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In code snippets in this article I assume we have &lt;code&gt;Database&lt;/code&gt; object in scope with method &lt;code&gt;select&lt;/code&gt;, which returns &lt;code&gt;Promise&lt;/code&gt; resolving to array of documents.  It accepts as argument object with two properties: &lt;code&gt;idGreaterThan&lt;/code&gt; - which determines condition in database, and &lt;code&gt;limit&lt;/code&gt; - the number of returned documents, e.g &lt;code&gt;db.select({ idGreaterThan: 6, limit: 2})&lt;/code&gt; is equivalent to SQL query &lt;code&gt;SELECT * FROM exoplanets WHERE id &amp;gt; 6 ORDER BY id ASC LIMIT 2&lt;/code&gt;. In this article I have omitted implementation for &lt;code&gt;Database&lt;/code&gt; class however simple mock can be found in this &lt;a href="https://runkit.com/kmoskwiak/5e07544f761b77001b44c45f" rel="noopener noreferrer"&gt;RunKit Notebook&lt;/a&gt;. This notebook contains also working example of code we are about to write.&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;code&gt;readDocuments&lt;/code&gt; function generator
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Generators are functions which can be exited and later re-entered. Their context (variable bindings) will be saved across re-entrances.&lt;br&gt;
(source: &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function*" rel="noopener noreferrer"&gt;function* - JavaScript | MDN&lt;/a&gt;)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;MDN Web Docs gives excellent explanation about &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function*" rel="noopener noreferrer"&gt;function generators&lt;/a&gt; and &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols" rel="noopener noreferrer"&gt;iterators&lt;/a&gt; in Javascript. For sake of this article what we must know is that generators after being called return an iterator. And iterator is an object which can be used in for..of loop.&lt;/p&gt;

&lt;p&gt;Let's write our generator &lt;code&gt;readDocuments&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="cm"&gt;/**
* Iterate over database
* @generator
* @function readDocuments
* @param {number} limit maximum number of documents
* @yields {array} list of planets
*/&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nf"&gt;readDocuments&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Database&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
   &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;lastId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// initialize with min value&lt;/span&gt;
   &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;done&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// indicates end of iteration&lt;/span&gt;

   &lt;span class="k"&gt;while&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;done&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="c1"&gt;// select batch of documents and wait for database response&lt;/span&gt;
       &lt;span class="c1"&gt;// TODO: error handling&lt;/span&gt;
       &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;select&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
           &lt;span class="na"&gt;idGreaterThan&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;lastId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
           &lt;span class="na"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;limit&lt;/span&gt;
       &lt;span class="p"&gt;});&lt;/span&gt;

       &lt;span class="c1"&gt;// get id of last document&lt;/span&gt;
       &lt;span class="nx"&gt;lastId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

       &lt;span class="c1"&gt;// end iteration if there are less documents than limit&lt;/span&gt;
       &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
           &lt;span class="nx"&gt;done&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
       &lt;span class="p"&gt;}&lt;/span&gt;

       &lt;span class="c1"&gt;// yield result&lt;/span&gt;
       &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice two important things in the code above: &lt;code&gt;readDocuments&lt;/code&gt; is declared both with &lt;code&gt;async&lt;/code&gt; keyword and &lt;code&gt;function*&lt;/code&gt; expression. This function is a hybrid of asynchronous function and function generator and it has power of both. Let's analyze it from two perspectives.&lt;/p&gt;

&lt;p&gt;As an async function it allows us to await an asynchronous database operation. This means that the while loop will behave synchronously. Each select from database will be executed only after the previous has been finished.&lt;/p&gt;

&lt;p&gt;Instead of returning &lt;code&gt;result&lt;/code&gt; we &lt;code&gt;yield&lt;/code&gt; it. That's a part of being the function generator. As I mentioned above, generators return an iterator which can be used in for loops. Each time generator yields something program breaks up from function and goes to body of loop.&lt;/p&gt;

&lt;p&gt;This brings us to well known for..of loop, but in async variation.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// We need to place our loop inside another async function &lt;/span&gt;
    &lt;span class="c1"&gt;// so we can use await keyword&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="k"&gt;await &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;documents&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nf"&gt;readDocuments&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
        &lt;span class="c1"&gt;// This for loop behaves synchronously. &lt;/span&gt;
        &lt;span class="c1"&gt;// Next iteration will begin after execution of code inside this loop&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;doSomethingWithDocuments&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;documents&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That’s it! In &lt;a href="https://runkit.com/kmoskwiak/5e07544f761b77001b44c45f" rel="noopener noreferrer"&gt;Runkit&lt;/a&gt; example I just log planets to console every iteration. You should see output similar to the one below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DATABASE:  SELECT * FROM exoplanets ORDER BY id ASC LIMIT 4
APP: Got 4 items from database: Proxima Centauri b, Gliese 667 Cc, Kepler-442b, Kepler-452b. Done: false

DATABASE:  SELECT * FROM exoplanets WHERE id &amp;gt; 7 ORDER BY id ASC LIMIT 4
APP: Got 4 items from database: Wolf 1061c, Kepler-1229b, Kapteyn b, Kepler-62f. Done: false

DATABASE:  SELECT * FROM exoplanets WHERE id &amp;gt; 14 ORDER BY id ASC LIMIT 4
APP: Got 4 items from database: Kepler-186f, Luyten b, TRAPPIST-1d, TRAPPIST-1e. Done: false

DATABASE:  SELECT * FROM exoplanets WHERE id &amp;gt; 18 ORDER BY id ASC LIMIT 4
APP: Got 4 items from database: TRAPPIST-1f, TRAPPIST-1g, LHS 1140 b, Kepler-1638b. Done: false

DATABASE:  SELECT * FROM exoplanets WHERE id &amp;gt; 24 ORDER BY id ASC LIMIT 4
APP: Got 1 items from database: Teegarden c*. Done: true
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I hope you enjoyed this article. In next article in this series I will show how to use this tool to read large files when memory is limited. Stay tuned!&lt;/p&gt;




&lt;h4&gt;
  
  
  Acks 🦄
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Cover photo by  &lt;a href="https://unsplash.com/@florenciaviadana?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Florencia Viadana&lt;/a&gt;  on  &lt;a href="https://unsplash.com/?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;Exoplanets in examples taken from &lt;a href="https://en.wikipedia.org/wiki/List_of_potentially_habitable_exoplanets" rel="noopener noreferrer"&gt;Wikipedia&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>javascript</category>
      <category>database</category>
      <category>mongodb</category>
      <category>postgres</category>
    </item>
  </channel>
</rss>
