<?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: Sriram</title>
    <description>The latest articles on Forem by Sriram (@digi0ps).</description>
    <link>https://forem.com/digi0ps</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%2F418952%2F7182476f-010f-4937-830d-4af73fe9c2f4.jpg</url>
      <title>Forem: Sriram</title>
      <link>https://forem.com/digi0ps</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/digi0ps"/>
    <language>en</language>
    <item>
      <title>Making concurrent API requests in Go</title>
      <dc:creator>Sriram</dc:creator>
      <pubDate>Sun, 05 Jul 2020 08:25:42 +0000</pubDate>
      <link>https://forem.com/digi0ps/making-concurrent-api-requests-in-go-4jig</link>
      <guid>https://forem.com/digi0ps/making-concurrent-api-requests-in-go-4jig</guid>
      <description>&lt;p&gt;Making API calls from the backend is a pretty common scenario we all come across, especially when working with microservices. Sometimes we even have to make multiple calls at the same time and doing it sequentially will be inefficient. So in this article, let us see how to implement concurrency when making multiple API calls. &lt;/p&gt;

&lt;h3&gt;
  
  
  Encapsulating request code
&lt;/h3&gt;

&lt;p&gt;Taking a look at what we have got we have &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a struct called Comic which contains the fields required fields from the response&lt;/li&gt;
&lt;li&gt;a function to make the request to XKCD and to return the decoded response&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Comic&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Num&lt;/span&gt;   &lt;span class="kt"&gt;int&lt;/span&gt;    &lt;span class="s"&gt;`json:"num"`&lt;/span&gt;
    &lt;span class="n"&gt;Link&lt;/span&gt;  &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="s"&gt;`json:"link"`&lt;/span&gt;
    &lt;span class="n"&gt;Img&lt;/span&gt;   &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="s"&gt;`json:"img"`&lt;/span&gt;
    &lt;span class="n"&gt;Title&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="s"&gt;`json:"title"`&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;baseXkcdURL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"https://xkcd.com/%d/info.0.json"&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;getComic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;comicID&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;comic&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Comic&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;baseXkcdURL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;comicID&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewDecoder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Body&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;comic&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;comic&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;



&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  Getting started
&lt;/h3&gt;

&lt;p&gt;Now coming to our basic version of the code down.&lt;br&gt;
What it does is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;takes an integer array of comic IDs and loops over it&lt;/li&gt;
&lt;li&gt;for each ID, retrieves the response from &lt;code&gt;getComic&lt;/code&gt; and sets it in the map&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As you can see, the code is pretty straightforward and should function effectively in most cases. But the problem comes with execution time.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;start&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Execution Time: "&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Since&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;}()&lt;/span&gt;

    &lt;span class="n"&gt;comicsNeeded&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;comicMap&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Comic&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;comicsNeeded&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;comicsNeeded&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;comic&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;getComic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;continue&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;comicMap&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;comic&lt;/span&gt;
        &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Fetched comic %d with title %v&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;comic&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Title&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;A glance at the output can tell us that the output delivered is sequential as expected, since the each API call is made only after the previous one is done.&lt;/p&gt;

&lt;p&gt;So the execution took well above 7 seconds, which would not be ideal if the server was dealing with heavy load at scale. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://asciinema.org/a/2Zr4KJc6LphYAd3YZrG6SefCp" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fasciinema.org%2Fa%2F2Zr4KJc6LphYAd3YZrG6SefCp.svg" alt="asciicast"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Making it concurrent
&lt;/h3&gt;

&lt;p&gt;Compared to other languages, I believe that Go has much better concurrency support. We will be using goroutines here, they are lightweight threads that run concurrently and can be spawned easily, thanks to Go.&lt;/p&gt;

&lt;p&gt;After modifying the main function to spawn goroutines, here's how it looks like&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;start&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Execution Time: "&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Since&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;}()&lt;/span&gt;

    &lt;span class="n"&gt;comicsNeeded&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="m"&gt;11&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;22&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;33&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;44&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;55&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;66&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;77&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;88&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;99&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;100&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;comicMap&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Comic&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;wg&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;sync&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WaitGroup&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;comicsNeeded&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;wg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;comic&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;getComic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&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="n"&gt;comicMap&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;comic&lt;/span&gt;
            &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Fetched comic %d with title %v&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;comic&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Title&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;wg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Done&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;}(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;wg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Wait&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;Okay, what's different? &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;We are creating a WaitGroup first in  &lt;code&gt;wg := sync.WaitGroup&lt;/code&gt;. The waitgroup can be thought of as a global counter which we can use to wait for all the goroutines to finish.&lt;/li&gt;
&lt;li&gt;While we loop over the &lt;code&gt;comicNeeded&lt;/code&gt; array, &lt;code&gt;wg.Add(1)&lt;/code&gt; is used to indicate that we are creating a goroutine.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;go func(){...}()&lt;/code&gt; fires the anonymous function as a separate goroutine. The id argument is used to capture the loop variable at that point of time. &lt;/li&gt;
&lt;li&gt;Inside the goroutine, we wait for &lt;code&gt;getComic&lt;/code&gt; so we can append it to the map. Once that is done &lt;code&gt;wg.Done()&lt;/code&gt; this indicates that this goroutine has finished.&lt;/li&gt;
&lt;li&gt;And finally after the loop is over, we call &lt;code&gt;wg.Wait()&lt;/code&gt;. Why is this necessary?
When spawning of all the goroutines has been completed, the main thread has no work left to do, which will intuitively lead to its termination. However, it is undesirable, as it causes all the goroutines to quit. So in order to make the main thread wait till all the spawned goroutines are marked as done, we perform &lt;code&gt;wg.Wait()&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Phew, now take a look at the output.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://asciinema.org/a/SVgghMjYOHRX0a4qkDwAi0UfW" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fasciinema.org%2Fa%2FSVgghMjYOHRX0a4qkDwAi0UfW.svg" alt="asciicast"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Woah, a reduction in execution time by a huge factor! The calls are not sequential as each goroutine executes independently based on the CPU availability. &lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;To wrap it up concurrency, depending on the application, can give huge performance boosts to your code. I wanted to do this using Channels at first but later realised that it could be done much simpler using just WaitGroups. But I do have a blog next planned with the use of channels in the same context. &lt;/p&gt;

&lt;h3&gt;
  
  
  Notes
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=cN_DpYBzKso&amp;amp;t=212s" rel="noopener noreferrer"&gt;Concurrency should not be confused with parallelism.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://gobyexample.com/goroutines" rel="noopener noreferrer"&gt;Goroutines&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://gobyexample.com/waitgroups" rel="noopener noreferrer"&gt;Waitgroups&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>go</category>
      <category>concurrency</category>
      <category>api</category>
      <category>microservices</category>
    </item>
    <item>
      <title>Connection Pooling — what and why?</title>
      <dc:creator>Sriram</dc:creator>
      <pubDate>Thu, 23 Apr 2020 07:47:09 +0000</pubDate>
      <link>https://forem.com/digi0ps/connection-pooling-what-and-why-bom</link>
      <guid>https://forem.com/digi0ps/connection-pooling-what-and-why-bom</guid>
      <description>&lt;p&gt;I came across connection pooling recently when I was working on a large scale microservice in Clojure and realised the HUGE impact it has on performance even when you are talking about serving a couple of hundred users.&lt;/p&gt;

&lt;p&gt;Having worked a lot in backend why didn’t I know this before? Maybe Django (my favourite backend suite) had abstracted it away in it’s ORM or I didn’t work in codebases where performance was paramount. 😛&lt;/p&gt;

&lt;h3&gt;
  
  
  But first what is a connection?
&lt;/h3&gt;

&lt;p&gt;A connection can be formally defined as a way for a client to talk with the server. It is required to send commands and receive a result.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--A-gR6ruS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AIhSEaqgdWbFiDq4wOBYCOA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--A-gR6ruS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AIhSEaqgdWbFiDq4wOBYCOA.png" alt="Image depicting connection request and response."&gt;&lt;/a&gt;Different types of connections&lt;/p&gt;

&lt;p&gt;For example, a browser talks to your favourite website using a TCP connection. Similarly a database connection lets you issue commands and receive answers in the form of a result set.&lt;/p&gt;

&lt;p&gt;Connection pooling can be applied to any connection like a TCP connection, database connection or even a Redis connection. But in this article, I will be taking focussing on examples about database connections.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is the problem with normal connections?
&lt;/h3&gt;

&lt;p&gt;Assume we have a Postgres database and you want to run this query on it.&lt;/p&gt;

&lt;p&gt;select chairs from dining_table;&lt;/p&gt;

&lt;p&gt;To get the result, along with this query we need to provide the database details and our authentication details, usually the &lt;em&gt;host, port, database, username and password&lt;/em&gt;. These are needed because before actually running the query, the program has to:&lt;/p&gt;

&lt;p&gt;→ find the database&lt;br&gt;&lt;br&gt;
→ connect to it&lt;br&gt;&lt;br&gt;
→ authenticate our connection&lt;br&gt;&lt;br&gt;
→ use the given db&lt;br&gt;&lt;br&gt;
→ and then run our query.&lt;/p&gt;

&lt;p&gt;Once the result is returned, the connection is closed. When we want to run a different query we need to start over again.&lt;/p&gt;

&lt;p&gt;As you can see we this is time consuming. Authentication is a very expensive process and most of the times creating connections take relatively longer compared to the actual query they run. So it becomes very inefficient for us to create a connection for every query.&lt;/p&gt;

&lt;p&gt;So instead of closing the connection, keeping it active and running all the queries using the same connection gets rid of this creation latency. But in a service, how do we share a connection between different clients? That is where connection pooling comes in.&lt;/p&gt;
&lt;h3&gt;
  
  
  Connection Pooling
&lt;/h3&gt;

&lt;p&gt;Connection Pooling alleviates this problem by creating a pool of connections at the start and keeping them alive (i.e not closing the connections) till the end. Whenever some part of the application wants to query the database, they borrow the connection from the pool and once they are done with the query instead of closing the connection, it is returned back to the pool. As simple as that.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--oWZCOSpZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2A0ycWme3iP4Wp6rHkxpticQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--oWZCOSpZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2A0ycWme3iP4Wp6rHkxpticQ.png" alt=""&gt;&lt;/a&gt;A connection pool example with one connection being idle&lt;/p&gt;

&lt;p&gt;Using this manner, even a small number of connections pooled can serve a large number of requests as the overhead of authentication for every request is eliminated.&lt;/p&gt;

&lt;p&gt;There are a lot of amazing connection pooling libraries out there like HikariCP, c3p0 etc. Most of these allow you to configure things like min-thread, max-thread, idle-timeout to make the connection pool suit our needs.&lt;/p&gt;
&lt;h3&gt;
  
  
  Performance Gains
&lt;/h3&gt;

&lt;p&gt;For you to actually see how much of a difference connection pooling gives, I decided to run a simple select query multiple times in two ways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Opening and closing a connection every time to execute the query&lt;/li&gt;
&lt;li&gt;Keeping an active connection and running the query in a loop&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I wrapped these two commands in a shell script to benchmark it and ran the script.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2-aNG_Am--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/664/1%2AbRy8Qg45NGMhm5EkV6khQQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2-aNG_Am--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/664/1%2AbRy8Qg45NGMhm5EkV6khQQ.png" alt=""&gt;&lt;/a&gt;Output!&lt;/p&gt;

&lt;p&gt;The output is shocking indeed. Though both the commands run the same query 100 times, the former loops externally in the shell causing the script to open and close a connection with Postgres every time to get the result.&lt;/p&gt;

&lt;p&gt;While the latter opens a connection at start using your authentication credentials and keeps it alive till you close the shell. Every query that is run inside the Postgres shell uses the existing active connection so there is no extra latency other than the time taken for query execution. Thus using the active connection gives you a performance boost of  &lt;strong&gt;77x.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;To conclude, connection pooling is quintessential to improve a backend service’s performance. It is not only limited to use with database connections but is also used widely in pooling TCP connections when it comes to interacting with other services.&lt;/p&gt;

</description>
      <category>database</category>
      <category>connection</category>
      <category>backend</category>
      <category>postgres</category>
    </item>
    <item>
      <title>Creating animations in Javascript using requestAnimationFrame</title>
      <dc:creator>Sriram</dc:creator>
      <pubDate>Sun, 19 May 2019 07:37:03 +0000</pubDate>
      <link>https://forem.com/digi0ps/creating-animations-in-javascript-using-requestanimationframe-11nh</link>
      <guid>https://forem.com/digi0ps/creating-animations-in-javascript-using-requestanimationframe-11nh</guid>
      <description>&lt;p&gt;Animations in Javascript? I bet keyframes are better._ I have almost entirely used CSS to create animations for my websites. In fact, I rarely use Javascript directly to touch the styles of an element. But I recently stumbled upon a tutorial using requestAnimationFrame for animations. I expected the usage of it to be complex, but it was very &lt;em&gt;simple&lt;/em&gt; yet &lt;em&gt;powerful&lt;/em&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Animations in JavaScript before requestAnimationFrame
&lt;/h3&gt;

&lt;p&gt;Before requestAnimationFrame, it was common to see people use setInterval to update styles of elements so that it was animated similar to the given code below. For a smooth animation we need to match the display framerate, which is 60fps, so we need to execute our function for 60 times per second which translates to an interval of  &lt;strong&gt;17ms&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="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;progressBar&lt;/span&gt; &lt;span class="o"&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;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#progress-bar&lt;/span&gt;&lt;span class="dl"&gt;'&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;width&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;updateProgressBar&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;progressBar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;width&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;width&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;%&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="nx"&gt;width&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&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;width&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
    &lt;span class="nx"&gt;clearInterval&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="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;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;setInterval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;updateProgressBar&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;17&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;A function, which updated the style of the element, was executed repeatedly on set intervals. Though this &lt;em&gt;did the job&lt;/em&gt;, it wasn’t an effective way. There were many disadvantages for this approach. The timer wasn’t accurate i.e the browser would give priority to other UI tasks over this. The function would keep executing even if the user is in some other tab and depending on the execution it meant higher CPU usage.&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/digi0ps/embed/xeyXGg?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h3&gt;
  
  
  Now what is requestAnimationFrame?
&lt;/h3&gt;

&lt;p&gt;requestAnimationFrame was developed to overcome the shortcomings of the &lt;strong&gt;setInterval/setTimeout&lt;/strong&gt; approach providing a native API to run any type of animation. It takes in a function as it’s argument and tells the browser to execute that function before the next repaint.&lt;/p&gt;

&lt;p&gt;It is very similar to setInterval except we are requesting the browser to execute the animation at the next available opportunity instead of predefined interval.&lt;/p&gt;

&lt;p&gt;Browsers generally optimize execution based on load, battery and element visibility on screen. All the animations are grouped into a single repaint, thus reducing the number of CPU cycles required. The animations are also halted when the user switches to a different tab. Yay!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--oLPNQE15--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://cdn-images-1.medium.com/max/480/1%2AsdoJ3O2cZiPTrrm9WezNmQ.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--oLPNQE15--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://cdn-images-1.medium.com/max/480/1%2AsdoJ3O2cZiPTrrm9WezNmQ.gif" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now doing the same progress bar with requestAnimationFrame gives us&lt;br&gt;
&lt;/p&gt;

&lt;div class="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;updateProgressBar&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;progressBar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;width&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;width&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;%&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="nx"&gt;width&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&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;width&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
    &lt;span class="nx"&gt;requestAnimationFrame&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;updateProgressBar&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="nx"&gt;requestAnimationFrame&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;updateProgressBar&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;As we can see, we call the &lt;strong&gt;requestAnimationFrame&lt;/strong&gt; initially and then recursively keep calling it until the required &lt;em&gt;width&lt;/em&gt; level is reached. Clearly, this syntax is much better than setInterval.&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/digi0ps/embed/QPZmGG?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h3&gt;
  
  
  Gravity using requestAnimationFrame
&lt;/h3&gt;

&lt;p&gt;Now let’s try to use requestAnimationFrame to implement (a more complex) animation for a Ball experiencing free-fall under gravity.&lt;/p&gt;

&lt;p&gt;We will be building a page which creates a ball everytime the user clicks on the page and the ball falls to the bottom. We will be trying to create mimic gravity for the fall.&lt;/p&gt;

&lt;p&gt;First we will write a function to create a &lt;strong&gt;ball-like element.&lt;/strong&gt; The ball will be div (with &lt;em&gt;border-radius&lt;/em&gt; 50%) positioned absolutely. We will pass this function the &lt;strong&gt;x, y&lt;/strong&gt; coordinates received from the click event.&lt;br&gt;
&lt;/p&gt;

&lt;div class="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;createBall&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;top&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;left&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="nx"&gt;ball&lt;/span&gt; &lt;span class="o"&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;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;div&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;ball&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;classList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ball&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;ball&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;top&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;top&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;px&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;ball&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;left&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;left&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;25&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;px&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&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;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;appendChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;$ball&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;ball&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;Here we are creating a &lt;strong&gt;div,&lt;/strong&gt; adding the class &lt;em&gt;ball&lt;/em&gt; and sets the top/left values before returning the created element.&lt;/p&gt;

&lt;p&gt;Next we write a function for initialising the fall animation which creates a function to deal with styles and initialises the animation frame request.&lt;br&gt;
&lt;/p&gt;

&lt;div class="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;initFalling&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ball&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="nx"&gt;ballHeight&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;acceleration&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;9.8&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;60&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;innerHeight&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;window&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;fallingSpeed&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;animateFall&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="nx"&gt;top&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;parseInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ball&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;top&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;newTop&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;top&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;fallingSpeed&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;px`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// To break the fall, when the ball is near the surface&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;parseInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;newTop&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;innerHeight&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;ballHeight&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;ball&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;top&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerHeight&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;ballHeight&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;px&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nx"&gt;ball&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;background&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;red&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Else set the top to the new value&lt;/span&gt;
    &lt;span class="nx"&gt;ball&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;top&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;newTop&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;fallingSpeed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;fallingSpeed&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;acceleration&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;requestAnimationFrame&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;animateFall&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="nx"&gt;requestAnimationFrame&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;animateFall&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;Let’s breakdown this function.&lt;/p&gt;

&lt;p&gt;Every ball starts with a fallingSpeed of 0 and is accelerated with every execution. Since acceleration due to gravity is 9.8m/s per second and the browser executes our function 60 times each second (general display framerate), so the acceleration per execution is  &lt;strong&gt;9.8/60&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;We write another function inside function and call it &lt;strong&gt;animateFall&lt;/strong&gt;. This will be the main function which will be passed to requestAnimationFrame. Pretty straight forward stuff inside. We retrieve the &lt;em&gt;top&lt;/em&gt; of the ball and add &lt;em&gt;falling speed to it.&lt;/em&gt; We check if this &lt;strong&gt;newTop&lt;/strong&gt; value is greater the window’s &lt;strong&gt;innerHeight.&lt;/strong&gt; If it is not, then we set it to the new value and increment &lt;strong&gt;fallingSpeed&lt;/strong&gt; before requesting an animation frame again. If the &lt;strong&gt;newTop&lt;/strong&gt; is greater, then the ball has hit the surface so we return from the function.&lt;/p&gt;

&lt;p&gt;We are nearly done, all we have to do now is create a event handler and chain these two functions together.&lt;br&gt;
&lt;/p&gt;

&lt;div class="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;onClickListener&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;event&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;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;y&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ball&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;createBall&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;initFalling&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ball&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&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;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;click&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;onClickListener&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The event coordinates and the positioning coordinates are inverted. That is x here is equivalent to the left in positioning and y is equivalent to the top. And &lt;em&gt;skadoosh&lt;/em&gt; we have created a &lt;em&gt;free falling portal.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/digi0ps/embed/eoPQWy?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h3&gt;
  
  
  We can still make this better
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Dying Animation;&lt;/strong&gt; added a dying animation based on the impact of the collision. The falling speed is an indicator of how long the ball has travelled in air. So we can add a fading animation in which balls which have travelled more fade faster and those which have travelled less fade slowly.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Randomness;&lt;/strong&gt; added a random factor for the color and size of the ball.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Organize;&lt;/strong&gt; orgainize the code into components using &lt;em&gt;Typescript + Webpack.&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  When should I use this instead of keyframes?
&lt;/h3&gt;

&lt;p&gt;Though the performance of both requestAnimationFrame and keyframes/transitions are very close, we can stick to CSS animations for most of the cases.&lt;/p&gt;

&lt;p&gt;Animating using JavaScript becomes super useful if the animation depends on some state or data, like the example above where we managed the fall of the ball using JS. We can also use it to create more complex animations like staggering animations or trailing animations (cue: I will be making a tutorial on trailing animations next).&lt;/p&gt;

&lt;h3&gt;
  
  
  References
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame"&gt;Window.requestAnimationFrame()&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://researchhubs.com/post/computing/javascript/requestAnimationFrame.html"&gt;requestAnimationFrame - The secret to silky smooth JavaScript animation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/Performance/CSS_JavaScript_animation_performance"&gt;CSS and JavaScript animation performance&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;And…&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--DdlQl5yV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://cdn-images-1.medium.com/max/640/1%2AyNMpWj2Qwis_XVDYcdhoPw.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--DdlQl5yV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://cdn-images-1.medium.com/max/640/1%2AyNMpWj2Qwis_XVDYcdhoPw.gif" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Thank you for reading!&lt;/p&gt;

</description>
      <category>css</category>
      <category>javascript</category>
      <category>animation</category>
    </item>
    <item>
      <title>GSoC ’18 with WorldBrain : The Journey</title>
      <dc:creator>Sriram</dc:creator>
      <pubDate>Tue, 14 Aug 2018 12:49:04 +0000</pubDate>
      <link>https://forem.com/digi0ps/gsoc-18-with-worldbrain-the-journey-421j</link>
      <guid>https://forem.com/digi0ps/gsoc-18-with-worldbrain-the-journey-421j</guid>
      <description>&lt;p&gt;Hello World. This is Sriram coming straight out of a really exciting and productive summer. This summer, I got selected to GSoC through WorldBrain to work on their browser extension Memex. It proved to be awesome working there. Here comes the blogpost about my entire GSoC journey&lt;/p&gt;

&lt;h3&gt;
  
  
  Pre GSoC
&lt;/h3&gt;

&lt;p&gt;As a freshman in college last year, I was very keen on getting into the GSOC. To take a step forward, I gave a shot at Zulip. Though that didn’t turn out well, it gave me an amazing learning experience. You can read more about that in this article I wrote a while ago.&lt;/p&gt;

&lt;p&gt;With the hopes of getting into GSoC gone, I didn’t want to waste an entire summer. I decide to learn something new and went for the most trending framework at that point of time, &lt;a href="https://react.com"&gt;React&lt;/a&gt;! Ended up getting quite a grasp of it over the summer and even refactored my old website completely in React. In no time, I started working on many more projects in React, enhancing my confidence in the area.&lt;/p&gt;

&lt;p&gt;Time flew and soon it was February ’18. GSoC organisations list was up, and I was still confused over which one was I going to choose.&lt;/p&gt;

&lt;h3&gt;
  
  
  WorldBrain
&lt;/h3&gt;

&lt;p&gt;Scrolling through the list of GSoC ’18 organisations, I was specifically looking for projects involving React. I found WorldBrain and their &lt;a href="https://medium.com/@WorldBrain/where-we-are-heading-with-worldbrain-65f244f540b8"&gt;vision for the web&lt;/a&gt; caught my eye!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;WorldBrain&lt;/strong&gt; is an open-source software collective with the mission of making it 10X+ faster for people to organise, recover, share and discover the most useful and knowledge-expanding content on the web. &lt;strong&gt;Memex&lt;/strong&gt; , which is there first product, is a free browser extension which solves one of the most frustrating experiences of doing online research: organising and finding websites again.&lt;/p&gt;

&lt;p&gt;I was every excited to try their extension, &lt;a href="https://worldbrain.io/"&gt;Memex&lt;/a&gt;. I did and Oh boy I loved it, being a student myself, it proved really helpful in finding sites which I had already visited before. Soon, I got myself introduced to my peers, who happened to be very friendly. First, I had to choose the project I wanted to work on from their idea list. Although there were many interesting ideas in front of me, I went for the one that seemed relatively easy to work on. :D&lt;/p&gt;

&lt;p&gt;The idea of this project was to show Memex’s search results a box alongside Google’s search results. Basically, I had to get the content script running in all pages; if the page’s URL matches the Google’s search url, fetch Memex results and render it on the page. All the discussion, implementation . and code of this feature can be found in &lt;a href="https://github.com/WorldBrain/Memex/pull/320"&gt;this PR&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Q-Zacn2H--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2A3N2StiScvmk7FGAnM8XL0Q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Q-Zacn2H--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2A3N2StiScvmk7FGAnM8XL0Q.png" alt=""&gt;&lt;/a&gt;Memex results injected alongside Google search results&lt;/p&gt;

&lt;h3&gt;
  
  
  About the project
&lt;/h3&gt;

&lt;p&gt;Even though the above mentioned one was a GSoC project, I finished it much before GSoC, which resulted me in changing my project to what it is right now - &lt;a href="https://github.com/WorldBrain/Memex/issues/301"&gt;Comments and Annotations&lt;/a&gt;; with the help of &lt;a href="https://github.com/oliversauter"&gt;Oliver&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;WorldBrain’s vision is to &lt;em&gt;have a p2p social network for collaborative web research&lt;/em&gt;. One of the important steps for that is the need for people’s interactions with content such as highlights, comments or ratings. These interactions would help an user know more about the authenticity, quality and useful information of every website they visit.&lt;/p&gt;

&lt;p&gt;My project helps achieve this vision by adding the ground work for this. It adds the ability to highlight any piece of text on the internet and store it along with a comment. The user will be able to see the comments/annotations he made in each page he visits. With this established; features such as sharing the annotations within an user’s network, giving quality ratings etc. could be easily added in the future.&lt;/p&gt;

&lt;h3&gt;
  
  
  Work 💻
&lt;/h3&gt;

&lt;p&gt;Fast forward to coding period: &lt;a href="https://github.com/ShishKabab"&gt;Vincent&lt;/a&gt;, an awesome developer at WorldBrain, had built the backend for a new Memex feature called Memex Link (previously known as DirectLink) which allowed users to highlight a piece of text and get an URL to share it. It was super cool. So my first tasks for the summer was writing the code to bring the Memex Link tooltip up in every page (&lt;a href="https://github.com/WorldBrain/Memex/pull/398"&gt;PR #398&lt;/a&gt;) and making the demo UI prettier (&lt;a href="https://github.com/WorldBrain/direct-linking-backend/pulls?utf8=%E2%9C%93&amp;amp;q=is%3Apr+author%3Adigi0ps"&gt;Link to all my PRs related to this task&lt;/a&gt;). Soon &lt;a href="http://memex.link"&gt;Memex.Link&lt;/a&gt; was put into production and it turned out to be a really cool feature.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--vRNNqgY1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2Aeqjg3orqa_QPxCcJaZCDiA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vRNNqgY1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2Aeqjg3orqa_QPxCcJaZCDiA.png" alt=""&gt;&lt;/a&gt;Memex tooltip in action with Annotate and Share buttons.&lt;/p&gt;

&lt;p&gt;By this time, I had also started my work on adding a sidebar to display all the user’s annotations on each website. There were two versions to this sidebar: one on Memex’s overview page and the other as an overlay on every website. Getting the former up and running was relatively easier compared to the latter. After a quick &lt;a href="https://github.com/WorldBrain/Memex/issues/301#issuecomment-395864771"&gt;discussion&lt;/a&gt;, I decided to go with the iFrame approach. Through the content_script I would inject a button ( called Ribbon ) and an iframe (which loads the sidebar stored as a separate html) and when the user clicks the Ribbon it shows the sidebar. After some struggle, I got the initial design up and running on both, the overview and the iFrame.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8d6EgzAd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/0%2AaUp15LrE3uNIX74L.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8d6EgzAd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/0%2AaUp15LrE3uNIX74L.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I was planning on tackling the storage of annotations next, but the initial designs weren’t really pleasing and I was given an UI overhaul to work on. For the next couple of weeks I worked on the UI and all the styling-related bugs that popped up. Oliver wanted it all pixel perfect. Although it was a struggle to get all the minute details done, it resulted in a more intuitive and aesthetically pleasing UI.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--DMWfX0Tj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2APcKoT8JdN6FNZ-I-ZlUeRQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--DMWfX0Tj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2APcKoT8JdN6FNZ-I-ZlUeRQ.png" alt=""&gt;&lt;/a&gt;Memex sidebar with new UI on top of a webpage containing few annotations&lt;/p&gt;

&lt;p&gt;Next came the storing of annotations with tags, which went smoothly compared to the previous parts. With the storage part done, an MVP was nearly ready. Finally, the part which I found most exhausting were the interactions between the frame and it’s parent page (for example: highlighting/scrolling on hovering the annotation container in the iFrame).&lt;/p&gt;

&lt;p&gt;Although, there were already existing methods to communicate between the extension scripts there weren’t any to support communication between a website and an extension page inside an iframe. So I wrote my own &lt;a href="https://github.com/WorldBrain/Memex/blob/develop/src/sidebar-overlay/messaging.ts"&gt;Class&lt;/a&gt; which served as a wrapper around the window.postMessage allowing the execution of remote functions on both the sides.&lt;/p&gt;

&lt;h3&gt;
  
  
  Production 🎉
&lt;/h3&gt;

&lt;p&gt;After tons of nifty feature additions, repercussions and bugs, we finally got the Comments and Annotations into productions. 🎉 It is LIVE and being used by 8000+ Memex users right now. Do check it out, by downloading their &lt;a href="https://worldbrain.io/#"&gt;Chrome/Firefox/Vivaldi extension&lt;/a&gt;. It was such a rewarding feeling seeing my work being used by others in production! ❤&lt;/p&gt;

&lt;p&gt;The last week was dedicated to cleaning up, refactoring and writing tests. And right now as am finishing up this article, I’m working on adding UI tests with Jest + Puppeteer.&lt;/p&gt;

&lt;h3&gt;
  
  
  Demo
&lt;/h3&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/7aZZmw7warI"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/2VhlZhqJWKI"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h3&gt;
  
  
  Important Links
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/WorldBrain/Memex/pull/411"&gt;Comments/Annotations Pull Request&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/WorldBrain/Memex/pulls?utf8=%E2%9C%93&amp;amp;q=is%3Apr+author%3Adigi0ps+"&gt;All Pull Requests during GSoC&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://storage.googleapis.com/summerofcode-prod.appspot.com/gsoc/core_project/doc/5927534777597952_1522166272_Comments_and_Annotation_Proposal_by_Sriram.pdf?Expires=1534268084&amp;amp;GoogleAccessId=summerofcode-prod%40appspot.gserviceaccount.com&amp;amp;Signature=NQziGNSdZN5dT77oHg5v54kT6%2B7zlK6ZW%2FgF4IwUO2lxh22lWjwvmvTYYEwGcXXMXUFMjjgCorgHMec4zKWoCZEF7Qd8WI5U298MYuxq3YJCAgCFz67ypQv%2BeYUTLS94Vx6AKcDhzbZ2ndn1fs8Cs3k9gRvHxh10Vdm9CJ9Be%2BAIH0hnVOqqI6vwTl0cyf5oBJuaGHVUVdqLAYpGRhC3tnkjkHCejbV13RPT%2FShS%2FsrFj97kA2mJYcGkEZNzQnrgzTDzUEiVwiuq5Wa9yj5pqqpPvw14PVqVxBtkJFdgZZzK8Bb7IyoxSFhTrzqfWFCUmAEea9r3kalf0DcKrH5RxQ%3D%3D"&gt;GSoC Proposal&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/digi0ps"&gt;My Github&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  To sum it up
&lt;/h3&gt;

&lt;p&gt;There were a lot of things that I learnt through the course of GSoC.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Working in a professional environment exposed me to so many new etiquettes like the git flow, stand-ups etc.&lt;/li&gt;
&lt;li&gt;Realized the need of clean code and an organised file structure. The importance was legit visible when I was working with huge project directories.&lt;/li&gt;
&lt;li&gt;There were a lot of bugs which popped up as a result of some silly typo or negligence. So realized that testing thoroughly before pushing it is very critical.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;It was a reminiscing experience working with everyone at WorldBrain. I made a lot of mistakes and there were times where I slacked off or was not able to complete all the tasks but thanks to everyone, especially Oliver, Vincent and Jon for always being there to help out and guide me!&lt;/p&gt;

&lt;p&gt;~ Sriram&lt;/p&gt;

</description>
      <category>chromeextension</category>
      <category>javascript</category>
      <category>google</category>
      <category>gsoc</category>
    </item>
  </channel>
</rss>
