<?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>DEV Community: Rares Portan</title>
    <description>The latest articles on DEV Community by Rares Portan (@raresportan).</description>
    <link>https://dev.to/raresportan</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%2F407358%2F05f3c2bb-8259-45ee-b305-112bb8fe5fea.jpg</url>
      <title>DEV Community: Rares Portan</title>
      <link>https://dev.to/raresportan</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/raresportan"/>
    <language>en</language>
    <item>
      <title>Using fetch</title>
      <dc:creator>Rares Portan</dc:creator>
      <pubDate>Sat, 01 Aug 2020 14:21:18 +0000</pubDate>
      <link>https://dev.to/raresportan/using-fetch-5dgd</link>
      <guid>https://dev.to/raresportan/using-fetch-5dgd</guid>
      <description>&lt;p&gt;For years, the default way to call &lt;a href="https://dev.to/what-is-an-application-programming-interface/"&gt;APIs&lt;/a&gt; from a web page was XMLHttpRequest. But working with XMLHttpRequest was not easy, so on top of it were build lots of popular libraries like &lt;a href="https://api.jquery.com/jquery.ajax/"&gt;jQuery.ajax()&lt;/a&gt; or &lt;a href="https://github.com/axios/axios"&gt;Axios&lt;/a&gt; who wrapped the XMLHttpRequest functionality in a Promise based interface and also hiding away its complexities.&lt;/p&gt;

&lt;p&gt;These days browsers provide a better alternative to XMLHttpRequest: &lt;code&gt;fetch()&lt;/code&gt;. Recently I migrated some code that used Axios to fetch. I was surprised by how hard that was. &lt;/p&gt;

&lt;p&gt;Fetch has a few gotchas that we all should know about before we start using it, but using a native browser feature, should be preferred over a library, even for the simple fact that you can get rid of a few 3rd party kilobytes of JavaScript.&lt;/p&gt;

&lt;h2&gt;
  
  
  A simple example
&lt;/h2&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// the only required parameter is the URL&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://api.open-notify.org/astros.json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&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;// do something with the response&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&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;// do something with the error&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Fetch function returns a Promise. &lt;br&gt;
A Promise can be:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;resolved&lt;/code&gt; when it is successful (in this case when the response from the server is received )&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;rejected&lt;/code&gt; when it fails (in this case when the response from the server cannot be received)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Since the Promise is resolved/rejected at a later time, asynchronously, we need to register callback functions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;then&lt;/code&gt; is called when the promise is successful&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;catch&lt;/code&gt; is called when the promise fails&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Or if you prefer async / await, you can use that too:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;try&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;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
    &lt;span class="c1"&gt;// do something with the response&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// do something with the error&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;But any useful fetch() is a bit more complicated. &lt;br&gt;
The response of a fetch() request is a stream, so depending on the type of data returned by the server, you need to get the data from the stream. &lt;/p&gt;

&lt;p&gt;For example, if the server response is JSON, you need to call &lt;code&gt;response.json()&lt;/code&gt; that returns a Promise that resolves with the result of parsing the body text as JSON.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&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://api.open-notify.org/astros.json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// or .text(), .blob(), .arrayBuffer(), .formData()&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;data&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;// do something with data    &lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&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;// do something with the error&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We can use fetch() to load all kind of data, like image files, audio or video files:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&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;/image.jpg&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;blob&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="c1"&gt;// returns promise&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;blob&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;image&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;src&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createObjectURL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;blob&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;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&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;// do something with the error&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  How to handle errors
&lt;/h2&gt;

&lt;p&gt;Now here is something unexpected. Here is it, straight from &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API"&gt;MDN&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The Promise returned from fetch() won’t reject on HTTP error status even if the response is an HTTP 404 or 500. Instead, it will resolve normally (with ok status set to false), and it will only reject on network failure or if anything prevented the request from completing.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I have no idea why it's working like this, none of the alternatives work this way, but this happens when you fetch an URL and the server responds with a &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Status"&gt;4xx or 5xx error&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&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;response&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;// This code is executed even for 4xx-5xx errors!&lt;/span&gt;
        &lt;span class="c1"&gt;// But the response will not contain expected data!&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&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;// This is not called for 4xx-5xx errors!&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We need to detect these errors and handle them. The &lt;code&gt;response&lt;/code&gt; has an &lt;code&gt;ok&lt;/code&gt; flag that is set to false when the server responds with an error, so we can use that flag:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&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;response&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;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ok&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;error&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;statusText&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Fetch failed&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
            &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
        &lt;span class="p"&gt;}&lt;/span&gt; 
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;response&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;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// this is skipped for 4xx-5xx errors!&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&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;// this is now called for 4xx-5xx errors!&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We can extract error related code in a separate function so we can use it with multiple fetch calls:&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;function&lt;/span&gt; &lt;span class="nx"&gt;checkForErrors&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// &lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;statusText&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Fetch failed&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
        &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// or Promise.reject(error)&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;response&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&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;checkForErrors&lt;/span&gt;&lt;span class="p"&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;response&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// this is skipped for 4xx-5xx errors!&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&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;// this is now called for 4xx-5xx errors!&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Advanced usage
&lt;/h2&gt;

&lt;p&gt;Besides the URL, fetch accepts an object with different options&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&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;response&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="o"&gt;=&amp;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 they are (those with * in front are the default values)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// *GET, POST, PUT, DELETE, etc.&lt;/span&gt;
    &lt;span class="nx"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;cors&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// no-cors, *cors, same-origin&lt;/span&gt;
    &lt;span class="nx"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;no-cache&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// *default, no-cache, reload, force-cache, only-if-cached&lt;/span&gt;
    &lt;span class="nx"&gt;credentials&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;same-origin&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// include, *same-origin, omit&lt;/span&gt;
    &lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="c1"&gt;// 'application/x-www-form-urlencoded', multipart/form-data, text/plain&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="nx"&gt;redirect&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;follow&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// manual, *follow, error&lt;/span&gt;
    &lt;span class="nx"&gt;referrerPolicy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;no-referrer&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// no-referrer, *no-referrer-when-downgrade, origin, origin-when-cross-origin, same-origin, strict-origin, strict-origin-when-cross-origin, unsafe-url&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;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stringify&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="c1"&gt;// body data type must match "Content-Type" header&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This means the following are the same:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&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;response&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&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;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;GET&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;cors&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
        &lt;span class="na"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;default&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
        &lt;span class="na"&gt;credentials&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;same-origin&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
        &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="na"&gt;redirect&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;follow&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
        &lt;span class="na"&gt;referrerPolicy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;no-referrer-when-downgrade&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
        &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt; 
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="o"&gt;=&amp;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 dive into some of the options and see how we can use them.&lt;/p&gt;

&lt;h3&gt;
  
  
  method option
&lt;/h3&gt;

&lt;p&gt;By default fetch() will make a &lt;a href="https://www.restapitutorial.com/lessons/httpmethods.html"&gt;GET request&lt;/a&gt;. &lt;br&gt;
If you want to do a POST you'll need to set the method option to POST. Usually, you'll also send some data:&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;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Jon&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;city&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;London&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="p"&gt;{&lt;/span&gt;  
        &lt;span class="na"&gt;method&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;  
        &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
            &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="na"&gt;body&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="nx"&gt;stringify&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="p"&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;response&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  mode option
&lt;/h3&gt;

&lt;p&gt;The fetch mode can be cors, no-cors, or same-time.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="p"&gt;{&lt;/span&gt;  
       &lt;span class="na"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;cors&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt; 
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;CORS headers are used by some servers to accept requests only from certain domains (e.g. company.com doesn't accept requests from others.com)&lt;br&gt;
By default, the &lt;code&gt;cors&lt;/code&gt; mode is used by fetch. This means that if the server doesn't have the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS"&gt;CORS&lt;/a&gt; headers set correctly, the fetch will be canceled. These are the most frustrating errors I ever encountered.&lt;/p&gt;
&lt;h3&gt;
  
  
  credentials option
&lt;/h3&gt;

&lt;p&gt;To access some resources on some servers you need to authorized, e.g. to read your Gmail you need to be logged in with your Google credentials.&lt;/p&gt;

&lt;p&gt;You are asked to log in once, and any subsequent fetch requests made by your browsers are allowed if your requests include the credentials.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="p"&gt;{&lt;/span&gt;  
       &lt;span class="na"&gt;credentials&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;include&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt; 
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Usually, credentials are saved as cookies, and thus when you use credentials include, all cookies are sent to the server. And this can sometimes create problems, as some servers accept&lt;br&gt;
only a limited length of cookies.&lt;/p&gt;
&lt;h2&gt;
  
  
  Timeout
&lt;/h2&gt;

&lt;p&gt;Sadly fetch() doesn't provide out-of-the-box support for timeouts. This means that the fetch request will wait forever for the server to respond. &lt;/p&gt;

&lt;p&gt;Luckily we can implement this by wrapping the fetch in a Promise that we can resolve or reject:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// create a wrapper&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;fetchTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;timeout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;// return the promise&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;reject&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;timer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;setTimeout&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;reject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Request timed out&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="nx"&gt;timeout&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;clearTimer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;response&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;clearTimout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;timer&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;response&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&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;clearTimer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// clear the timer&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;resolve&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;reject&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="c1"&gt;// use the wrapper instead of fetch&lt;/span&gt;
&lt;span class="nx"&gt;fetchTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt; &lt;span class="mi"&gt;10000&lt;/span&gt;&lt;span class="p"&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;response&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; 
    &lt;span class="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;data&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;// do something with data    &lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&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;// do something with the error&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Cancel
&lt;/h2&gt;

&lt;p&gt;Sometimes we want to cancel a fetch(). &lt;/p&gt;

&lt;p&gt;Let's assume you are on Youtube or Netflix, you fetch a video but then you change your mind and want to see another video. You start fetching the new one, but what happens with the other one? You don't want to see it anymore so you want to cancel it. How you do that?&lt;/p&gt;

&lt;p&gt;Well, you can use &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/AbortController"&gt;AbortController&lt;/a&gt;, a shiny new experimental technology! (FYI It's already available in all major browsers)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// create a controller&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;controller&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;AbortController&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;signal&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;controller&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// call abort() if you want to cancel it&lt;/span&gt;
&lt;span class="nx"&gt;controller&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;abort&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Here is how you can use it with fetch, you pass the &lt;code&gt;signal&lt;/code&gt; as an option:&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;controller&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;AbortController&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;signal&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;controller&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="p"&gt;{&lt;/span&gt; 
        &lt;span class="nx"&gt;signal&lt;/span&gt;  
    &lt;span class="p"&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;response&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&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;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;AbortError&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
            &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Fetch aborted&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// error not caused by abort&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;


&lt;span class="c1"&gt;// Abort request&lt;/span&gt;
&lt;span class="nx"&gt;controller&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;abort&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;If you pass the same &lt;code&gt;signal&lt;/code&gt; to multiple fetch calls, &lt;code&gt;controller.abort()&lt;/code&gt; will cancel all requests with that signal.&lt;/p&gt;

&lt;p&gt;If you call .abort() after the fetch has completed, nothing happens, abort is ignored.&lt;/p&gt;

&lt;p&gt;It took a long time for the Abort API to be accepted: &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The key disagreement is one group wanted the abort method to exist on the object returned by fetch(),  whereas the other wanted a separation between getting the response and affecting the response. --  &lt;a href="https://developers.google.com/web/updates/2017/09/abortable-fetch#the_history"&gt;Jake Archibald&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I would prefer the object returned by fetch() to have the abort method. Since is best to keep the abort details hidden we would need to create a wrapper like this:&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;function&lt;/span&gt; &lt;span class="nx"&gt;abortableFetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;opts&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;controller&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;AbortController&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;signal&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;controller&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;signal&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="na"&gt;abort&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="nx"&gt;controller&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;abort&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="na"&gt;ready&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;signal&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;Because the above solution breaks the interface of the object returned by fetch(), we could add the abort() on that object (e.g. as proposed by the group that lost)&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;function&lt;/span&gt; &lt;span class="nx"&gt;abortableFetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;options&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;controller&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;AbortController&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;signal&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;controller&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// return the promise&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;promise&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{...&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;signal&lt;/span&gt;&lt;span class="p"&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;resolve&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nx"&gt;promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;abort&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="nx"&gt;controller&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;abort&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;promise&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This allows us to combine the timeout and cancel functionality in a single wrapper:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;
&lt;span class="cm"&gt;/**
 * Fetch that can timeout and is cancellable
 */&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;enhancedFetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;timeout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5000&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;controller&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;AbortController&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;signal&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;controller&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;signal&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;timer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;setTimeout&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;reject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Request timed out&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="nx"&gt;timeout&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;clearTimer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;response&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;clearTimout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;timer&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;response&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// return the promise&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;promise&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{...&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;signal&lt;/span&gt;&lt;span class="p"&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;clearTimer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// clear the timer&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;resolve&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nx"&gt;promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;abort&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="nx"&gt;controller&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;abort&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;promise&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;h2&gt;
  
  
  Progress
&lt;/h2&gt;

&lt;p&gt;We can track the download progress (but not upload progress) using &lt;code&gt;response.body&lt;/code&gt;, that is a &lt;a href="https://streams.spec.whatwg.org/#rs-class"&gt;ReadableStream&lt;/a&gt;, a source of data, from which we can read data as it becomes available.&lt;/p&gt;

&lt;p&gt;Unlike &lt;code&gt;response.json()&lt;/code&gt; and other methods, &lt;code&gt;response.body&lt;/code&gt; gives full control over the reading process, and we can see how much data is received at any moment.&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;progressIndicator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;total&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;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;https://reqres.in/api/users/1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&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;// get reader from response body&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;reader&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;response&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;getReader&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="c1"&gt;// get total length&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;contentLength&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Content-Length&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;receivedLength&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;let&lt;/span&gt; &lt;span class="nx"&gt;chunks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt; 

        &lt;span class="k"&gt;while&lt;/span&gt;&lt;span class="p"&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="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;done&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="p"&gt;}&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;reader&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;read&lt;/span&gt;&lt;span class="p"&gt;();&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;done&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;

            &lt;span class="nx"&gt;chunks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="nx"&gt;receivedLength&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Received &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;receivedLength&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; of &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;contentLength&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="c1"&gt;// here you can call a function with the current length&lt;/span&gt;
            &lt;span class="nx"&gt;progressIndicator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;receivedLength&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;contentLength&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="c1"&gt;// when all data is available it's time to parse it&lt;/span&gt;
        &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;contentArray&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Uint8Array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;receivedLength&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;position&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="k"&gt;for&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;chunk&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;chunks&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;contentArray&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;position&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
            &lt;span class="nx"&gt;position&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nx"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="c1"&gt;// decode content array into a string&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;new&lt;/span&gt; &lt;span class="nx"&gt;TextDecoder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;utf-8&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;contentArray&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="c1"&gt;// finally get data&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="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;parse&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="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Polyfill
&lt;/h2&gt;

&lt;p&gt;All major browsers support fetch these days, but if you want support for IE11 or some other old browser, you'll need to use a polyfill (like &lt;a href="https://github.com/github/fetch"&gt;https://github.com/github/fetch&lt;/a&gt;)&lt;/p&gt;

&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API"&gt;https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch"&gt;https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/AbortController"&gt;https://developer.mozilla.org/en-US/docs/Web/API/AbortController&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.github.io/fetch/#response-body"&gt;https://github.github.io/fetch/#response-body&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://davidwalsh.name/fetch-timeout"&gt;https://davidwalsh.name/fetch-timeout&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://davidwalsh.name/fetch"&gt;https://davidwalsh.name/fetch&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://fetch.spec.whatwg.org/"&gt;https://fetch.spec.whatwg.org/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developers.google.com/web/updates/2017/09/abortable-fetch"&gt;https://developers.google.com/web/updates/2017/09/abortable-fetch&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://javascript.info/fetch-progress"&gt;https://javascript.info/fetch-progress&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;Thanks for reading. This article was originally posted on &lt;a href="https://www.raresportan.com/using-fetch/"&gt;my blog&lt;/a&gt;.&lt;br&gt;
Cover Photo by K. Mitch Hodge on Unsplash&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>fetch</category>
    </item>
    <item>
      <title>How to Get 100 Website Performance Score</title>
      <dc:creator>Rares Portan</dc:creator>
      <pubDate>Tue, 07 Jul 2020 06:33:45 +0000</pubDate>
      <link>https://dev.to/raresportan/how-to-get-100-website-performance-score-1ppd</link>
      <guid>https://dev.to/raresportan/how-to-get-100-website-performance-score-1ppd</guid>
      <description>&lt;p&gt;First, let’s see what 100 website performance score means. A tool, called &lt;a href="https://developers.google.com/web/tools/lighthouse"&gt;Lighthouse&lt;/a&gt;, is used to measure website performance. The measurement is a score between 0 and 100. 100 means the best performance.&lt;/p&gt;

&lt;p&gt;This score is important in several ways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It’s an indicator of the user experience. If the website is slow, visitors will not wait and move on to other sites. This is even more important on mobile devices, which in general have a slow internet connection.&lt;/li&gt;
&lt;li&gt;It’s part of the Google Search Engine algorithm that determines the rank of the website for a search query. The lower the score, the lower the website ranking, given there are other sites that match the search query and have a better score.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Lighthouse is integrated into Chrome’s Developer Tools so you can use it from there, but you should use &lt;a href="https://web.dev/measure/"&gt;web.dev&lt;/a&gt; or &lt;a href="https://developers.google.com/speed/pagespeed/insights/"&gt;PageSpeed Insights&lt;/a&gt; because the DevTool's score is influenced by Chrome plugins you have installed.&lt;/p&gt;

&lt;p&gt;The tips presented here can be applied to any website, but as an example I'll use my website, &lt;a href="https://www.raresportan.com"&gt;https://www.raresportan.com&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Here is the performance score of my website using web.dev:&lt;a href="///static/772422e4c6077575d4fc47afd461bf7e/eee07/perf.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--F6XTPkLL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raresportan.com/static/772422e4c6077575d4fc47afd461bf7e/c5bb3/perf.png" alt="The performance score of this website" title="The performance score of this website"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The performance score is determined by &lt;a href="https://web.dev/vitals/"&gt;3 metrics&lt;/a&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Largest Contentful Paint (LCP): measures loading performance. To provide good user experience, LCP should occur within 2.5 seconds of when the page first starts loading.&lt;/li&gt;
&lt;li&gt;First Input Delay (FID): measures interactivity. To provide good user experience, pages should have an FID of less than 100 milliseconds.&lt;/li&gt;
&lt;li&gt;Cumulative Layout Shift (CLS): measures visual stability. To provide good user experience, pages should maintain a CLS of less than 0.1.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Why Go for 100?
&lt;/h2&gt;

&lt;p&gt;A score of 90+ is great, you are doing a great job. So why would someone want to go for 100?&lt;/p&gt;

&lt;p&gt;There is no good answer to this question. There’s not much of a difference between 90+ and 100 scores. People will have the same experience. The rank on Google will be the same. You’ll go for 100 only if you want to demonstrate that you can. That you go the extra mile. This is why I did it anyway.&lt;/p&gt;

&lt;p&gt;Why you should not go for it? If your website is very interactive, fetches data, uses buttons to post data, so is very dynamic, you’ll have a hard time reaching 100 because you’ll need to load too much JavaScript.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to Do It
&lt;/h2&gt;

&lt;p&gt;This can be done by removing a lot of JavaScript, embedding CSS and fonts and using less images and optimizing the images.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Remove Javascript
&lt;/h3&gt;

&lt;p&gt;JavaScript affects LCP &amp;amp; FID.&lt;/p&gt;

&lt;p&gt;I’m using Gatsby to build the website, the pages are rendered server-side and served as HTML to the browser. But after the HTML is loaded, it also loads 200k of JavaScript, including React. When React loads it adds interactivity to your buttons, fetches data, etc.&lt;/p&gt;

&lt;p&gt;Because the website has mostly links, few buttons, no data fetch, I removed all the JavaScript added by Gatsby using the &lt;a href="https://www.gatsbyjs.org/packages/gatsby-plugin-no-javascript/"&gt;&lt;code&gt;gatsby-plugin-no-javascript&lt;/code&gt;&lt;/a&gt; in &lt;code&gt;gatsby-config.js&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;module.exports = {
  plugins: [
      ...
      `gatsby-plugin-no-javascript` ]
}      
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;I have a button the website, the lightbulb next to the site name is used to change the theme. That was not working anymore after I’ve removed all the JavaScript, but I’ve solved this by reimplementing the functionality in plainJavaScript inside &lt;code&gt;html.js&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt; &amp;lt;script
    dangerouslySetInnerHTML={{
    __html: `
        var theme;
        try {
            theme = localStorage.getItem('theme');
        } catch (err) { }

        if(!theme &amp;amp;&amp;amp; window.matchMedia('(prefers-color-scheme: dark)') &amp;amp;&amp;amp; window.matchMedia('(prefers-color-scheme: dark)').matches) {                
            theme = 'dark'
        }               
        document.body.className = theme || 'light';

        function toggleTheme() {
            var body = document.querySelector('body');
            var newTheme = body.className === 'dark' ? 'light' : 'dark';                
            body.className = newTheme;
            try {
                localStorage.setItem('theme', newTheme);
            } catch (err) { }
        }`
    }}
/&amp;gt; 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Another thing that I did was to call the &lt;a href="https://dev.to/server-side-google-analytics/"&gt;analytics function&lt;/a&gt; from &lt;code&gt;html.js&lt;/code&gt; also, this way I don’t include Google Analytics scripts on the website:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;script
    dangerouslySetInnerHTML={{
    __html: `
        // send analytics data
        function sendData() {
            var sitedata = {
                ...
            }
            return fetch('/.netlify/functions/send', {
                body: JSON.stringify(sitedata),
                method: 'POST'
            })
        }
        sendData();
    `
    }}
 /&amp;gt;      
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;If you are using Twitter share on your website you might need to remove the Twitter library and replace the calls with plain links. Here is an example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;a href="https://twitter.com/share?url=https://raresportan.com/how-to-get-100-performance/&amp;amp;amp;text=How%20to%20Get%20100%20Website%20Performance&amp;amp;amp;via=raresportan" 
   target="_blank" 
   rel="noreferrer"&amp;gt;
    Please share it with your friends on Twitter    
&amp;lt;/a&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Embed Critical Styles
&lt;/h3&gt;

&lt;p&gt;CSS files affect CLS. If the CSS is loaded after the HTML is rendered, the page visuals are changing.&lt;/p&gt;

&lt;p&gt;Critical CSS must be added inside the HTML using a &lt;code&gt;&amp;lt;style&amp;gt;&lt;/code&gt; tag. Do not use a &lt;code&gt;.css&lt;/code&gt; file for your critical CSS.Lucky me, Gatsby does this by default. It concatenates the content of all CSS files in a single string that is added as &lt;code&gt;&amp;lt;style&amp;gt;&lt;/code&gt; tag inside the HTML.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Embed Fonts
&lt;/h3&gt;

&lt;p&gt;Just as CSS, fonts affect CLS. The moment the font is loaded, the texts on the page are re-rendered. And just as CSS, the fonts must be in the HTML, and not loaded as separate files.&lt;/p&gt;

&lt;p&gt;In my case, I creates a fonts.css that contains the font sources as base64 encoded strings. They end up inside the&lt;code&gt;&amp;lt;style&amp;gt;&lt;/code&gt; tag with the rest of the CSS.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@font-face {
    font-family: IBM Plex Sans;
    font-style: normal;
    font-display: swap;
    font-weight: 500;
    src: url(data:font/woff2;base64,d09GMgABAAAAAEjQABEAAAAAy...)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;I used a &lt;code&gt;base64&lt;/code&gt; command (available on macOS and Linux) to transform the fonts:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ base64 myfont.ttf &amp;gt; fontbase64.txt
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Alternatively, you can use an online service to do this.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Optimize Images
&lt;/h3&gt;

&lt;p&gt;You should use few images if possible. If not make sure you optimize the hell out of them.Always set a width and height or put them inside a container that has ‘overflow: hidden’, otherwise when an image is loaded it moved content around and this is very bad for the CLS.&lt;/p&gt;

&lt;p&gt;I’m using Gatsby’s plugins to optimize my images. It automatically generates different images for different viewport sizes and loads the images lazy:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;img class="gatsby-resp-image-image" 
    alt="The performance score of this website" 
    title="The performance score of this website" 
    src="/static/772422e4c6077575d4fc47afd461bf7e/c5bb3/perf.png" 
    srcset="/static/772422e4c6077575d4fc47afd461bf7e/04472/perf.png 170w,
            /static/772422e4c6077575d4fc47afd461bf7e/9f933/perf.png 340w,
            /static/772422e4c6077575d4fc47afd461bf7e/c5bb3/perf.png 680w,
            /static/772422e4c6077575d4fc47afd461bf7e/b12f7/perf.png 1020w,
            /static/772422e4c6077575d4fc47afd461bf7e/b5a09/perf.png 1360w,
            /static/772422e4c6077575d4fc47afd461bf7e/eee07/perf.png 1628w" 
            sizes="(max-width: 680px) 100vw, 680px" 
            loading="lazy" 
            style="width: 100%; height: 100%; margin: 0px; vertical-align: middle; position: absolute; top: 0px; left: 0px;"&amp;gt;

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



&lt;p&gt;Beside this I’m using a &lt;a href="https://www.npmjs.com/package/netlify-plugin-image-optim"&gt;Netlify plugin&lt;/a&gt; that optimizes the image even further.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Preload Pages
&lt;/h3&gt;

&lt;p&gt;One of the nice things Gatsby does is that it preloads all the pages referenced by a specific page. And thus navigation from one website page to another is instant.&lt;/p&gt;

&lt;p&gt;I loved that. But now that I’ve removed JavaScript, the navigation between pages is much slower.I almost give up at this point. While the initial page load was faster, the in-site navigation was worse.&lt;/p&gt;

&lt;p&gt;In the end, I wrote a bit of plain JavaScript that prefetch a page when the user hovers on the link. With this I save 100-300ms and the page are appearing to load faster:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;script
    dangerouslySetInnerHTML={{
    __html: `
        window.addEventListener('DOMContentLoaded', (event) =&amp;gt; {
            document.querySelector('button.lightbulb').addEventListener('click', toggleTheme);

            //only in-site links
            var links = document.querySelectorAll('a[href^="/"')
            links.forEach(function(link) {
                link.addEventListener('mouseover', function(e) {
                var l = e.target;
                var href = l.href; 
                var link = document.querySelector('link[href="'+href+'"]');
                if (!link) {
                    var prefetchLink = document.createElement("link");
                    prefetchLink.href = href;
                    prefetchLink.rel = "prefetch";
                    document.head.appendChild(prefetchLink);
                }
            })
        });        
    `,
    }}
/&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



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

&lt;p&gt;If you are willing to make some compromises, most importantly to replace kilos of JavaScript libraries with some vanilla JavaScript you can reach a 100 score in website performance.&lt;/p&gt;

&lt;p&gt;While you can do something about CSS and fonts, in most cases is probably not practical to remove all the JavaScript, and a 90+ score is fine.&lt;/p&gt;




&lt;p&gt;Thanks for reading. This article was originally posted on &lt;a href="https://www.raresportan.com/how-to-get-100-performance-score/"&gt;my blog&lt;/a&gt;.&lt;br&gt;
Cover Photo by ShareGrid on Unsplash&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>gatsby</category>
      <category>webperf</category>
    </item>
    <item>
      <title>What Makes Good Code Good</title>
      <dc:creator>Rares Portan</dc:creator>
      <pubDate>Fri, 12 Jun 2020 07:00:50 +0000</pubDate>
      <link>https://dev.to/raresportan/what-makes-good-code-good-5cn7</link>
      <guid>https://dev.to/raresportan/what-makes-good-code-good-5cn7</guid>
      <description>&lt;p&gt;There are things that make or break software, like good User Experience Design, marketing that should come up with the right features for the right app, or management that should pick up the right people for the right job.&lt;/p&gt;

&lt;p&gt;Those things might be out of your control. What you can control is the other important part: designing and writing the code. &lt;/p&gt;

&lt;p&gt;So the question is: What is good code? What should you look for? Ask ten people and you’ll get ten different answers. Read ten books and you’ll find ten different answers. Different people, different experiences, different problems, different contexts, different answers. &lt;/p&gt;

&lt;p&gt;Truth is there is no good answer. Context matters, timeframe matters, money matters.&lt;/p&gt;

&lt;h2&gt;
  
  
  How can we describe good code
&lt;/h2&gt;

&lt;p&gt;But no matter the situation or context, good code has a few evergreen qualities:&lt;/p&gt;

&lt;h3&gt;
  
  
  Simple
&lt;/h3&gt;

&lt;p&gt;The code is simple to understand, simple to modify, untangled, decoupled, obvious. This means the code is not complex, not tangled, not coupled, not spaghetti. &lt;/p&gt;

&lt;p&gt;Simple code doesn’t cause side effects outside of its scope &lt;br&gt;
and cannot be influenced by outside scopes. A classic example: if the code receives a mutable object as input, it will not change the object causing outside side effects, and any change to the object will not change the state of the code.&lt;/p&gt;

&lt;p&gt;But beware, simple does not necessarily mean &lt;em&gt;easy or familiar.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Clear
&lt;/h3&gt;

&lt;p&gt;Clarity of code means clarity of purpose. The code must tell what it’s doing at every level. There should be no obfuscations, no hidden things, no mess. It's clear in which state it is. It's clear if something is wrong. It's clear if it can’t complete its task or if it is waiting for something.&lt;br&gt;
Everything happens for a reason, and the reason should be clear.&lt;/p&gt;

&lt;p&gt;This is maybe the hardest thing to get right. Thousands of small or big decisions are taken in the lifetime of a codebase. And those decisions are lost. The whys are lost.&lt;/p&gt;

&lt;h3&gt;
  
  
  Reliable
&lt;/h3&gt;

&lt;p&gt;Works in the same way no matter the conditions or context. It is hard to be used in incorrect ways, hard to break. When incorrect input is used, the software clearly indicates why the input is wrong and what to use instead. It doesn’t return references to the inner state.&lt;/p&gt;

&lt;p&gt;This is the edge functional languages have over the object-oriented ones. Coding with immutable data is the most efficient way to create reliable code.&lt;/p&gt;

&lt;h3&gt;
  
  
  Efficient
&lt;/h3&gt;

&lt;p&gt;It is designed to be as fast as possible. It is designed to consume as little memory as possible.Everybody heard that &lt;em&gt;“premature optimisation is the root of all evil”.&lt;/em&gt; This quote was perverted in all possible ways as an excuse for slow and inefficient software. Just remember this: At the function level, you can always optimise later. But at higher design levels, you must plan for performance. &lt;/p&gt;

&lt;p&gt;You must think not only about the data flow but also  about the flow rate. If the design is bad, expect a laggy app.&lt;/p&gt;

&lt;h3&gt;
  
  
  Composable
&lt;/h3&gt;

&lt;p&gt;It means your code is built like everything else around you. Look around, you can always find a hierarchy, smaller things are combined to create greater things. By understanding the hierarchical structure of things, you can understand the roles each component plays and how they fit into the larger picture. &lt;/p&gt;

&lt;p&gt;Good code creates big systems from smaller ones, which are built from even smaller components.&lt;/p&gt;

&lt;h2&gt;
  
  
  Balance, compromise, and trade-offs
&lt;/h2&gt;

&lt;p&gt;Usually, some of these qualities are at odds with others. &lt;/p&gt;

&lt;p&gt;The clearest code might not be the fastest one. Most reliable code might not be the simplest. You need to find the right balance between them, depending on context and the problem you try to solve. &lt;/p&gt;

&lt;p&gt;First aim to make the code clear and simple. Then modify it to make it more reliable and efficient, giving up on some of the clarity and simplicity.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Easy to use almost mandates garbage collection, but that collides with ‘fast’ and ‘simple to implement’. Removing pointers makes the language safer, but at a steep loss of generality. Trying to make pointers safe with a ton of language rules makes the language hard to use. I could go on. - &lt;a href="https://berthub.eu/articles/posts/cpp-rust-go/"&gt;Bert Hubert&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Why don’t people code like that?
&lt;/h2&gt;

&lt;p&gt;This question has always intrigued me. Everybody likes to brag with their skills and knowledge and the awesome languages or tools they use. But somehow they make poor code. The answer is simple: it is easy to write bad code and quite hard to write good code. &lt;/p&gt;

&lt;p&gt;At some point, somebody made these observations about code implementations:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;CODE&lt;/th&gt;
&lt;th&gt;IMPLEMENTATION&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Appears to work&lt;/td&gt;
&lt;td&gt;Easy&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Correct&lt;/td&gt;
&lt;td&gt;Far more difficult&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Can be understood by others&lt;/td&gt;
&lt;td&gt;Very difficult&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Can be modified in the future&lt;/td&gt;
&lt;td&gt;Very very difficult&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Efficient&lt;/td&gt;
&lt;td&gt;Very very very difficult&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Most of the code is at the “appears to work” level. Some of it is “correct” and “can be understood by others.” Almost none “can be modified in the future” with the confidence that changes will not break something.This happens because people stop iterating on the code too soon. They think they are done when they are not. &lt;/p&gt;

&lt;p&gt;Everything, code and design, must be an iterative process.&lt;br&gt;
&lt;strong&gt;Software is never written, is always rewritten.&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;What you can do as a programmer, though, is get through the assignments doing something that works, and then look back at it and see how you could have made it better or faster or more concise. This is one thing that seriously differentiates programmers from excellent programmers. - &lt;a href="https://beej.us/guide/bgc/pdf/bgc_A4.pdf"&gt;Brian “Beej” Hall&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Simple vs. easy
&lt;/h2&gt;

&lt;p&gt;While most of the qualities of good code are obvious, one is not. &lt;br&gt;
People often don’t understand what simple code means. Many people think simple means easy. &lt;/p&gt;

&lt;p&gt;This is not true. Simple means something that works with one thing at a time or does one thing at a time.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;SIMPLE CODE&lt;/th&gt;
&lt;th&gt;EASY CODE&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;One purpose&lt;/td&gt;
&lt;td&gt;Many purposes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Values&lt;/td&gt;
&lt;td&gt;Objects&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Data&lt;/td&gt;
&lt;td&gt;Classes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Map/Reduce/Filter&lt;/td&gt;
&lt;td&gt;Imperative loops&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pure function&lt;/td&gt;
&lt;td&gt;Method mutating state&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Function that does a thing&lt;/td&gt;
&lt;td&gt;Add an “if” in a function&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Object using object&lt;/td&gt;
&lt;td&gt;Class extending class&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Consistency&lt;/td&gt;
&lt;td&gt;Inconsistency&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Implement yourself&lt;/td&gt;
&lt;td&gt;Download it from the Internet&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;See &lt;a href="https://www.infoq.com/presentations/Simple-Made-Easy/"&gt;Rich Hickey's illuminating presentation&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Trade-offs of doing simple code
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;SIMPLE CODE vs. EASY CODE&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Development starts slow vs. fast&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Development speed grows to a level vs. slows down forever&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Development speed remains constant vs. is near zero&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Simple code implies a slow start. Doing easy code, you get fast initial development time but it slows down constantly. At some point, after you have enough code, the development speed is near zero. &lt;/p&gt;

&lt;p&gt;For simple code, you get slow initial development time but it grows and remains at a constant level.Simple code requires more effort and discipline. You have to think more, you have to resist the easy way.&lt;/p&gt;

&lt;p&gt;Simple code is underrated and unappreciated. Usually, nobody notices it, but when they notice it they are not happy about it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Developers don’t notice it because it doesn’t get in their way.&lt;/li&gt;
&lt;li&gt;Teachers don’t like it because they think it is too mundane and below their level of intelligence.&lt;/li&gt;
&lt;li&gt;Consultants and methodologists don’t like it because they can’t ask a ton of money for something simple.&lt;/li&gt;
&lt;li&gt;Managers don’t like it because they think you waste too much time on trivial things. “What? You spent days thinking about this simple and obvious code? A novice would have done it in 5 minutes”&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Still, &lt;em&gt;there is nothing more sophisticated than simple code.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The parable of two programmers
&lt;/h2&gt;

&lt;p&gt;A while ago, two companies, the Automated Co. and the Consolidated Co. decided that they need the same program. Here is how they handled the problem.&lt;/p&gt;

&lt;h3&gt;
  
  
  Day 1
&lt;/h3&gt;

&lt;p&gt;Automated hires a very expensive consultant, Alan, to solve their problem. &lt;/p&gt;

&lt;p&gt;Consolidated decides to let one of their bright programmers, Charles, to do the job. &lt;/p&gt;

&lt;h3&gt;
  
  
  Day 10
&lt;/h3&gt;

&lt;p&gt;At Automated, Alan, with a long experience in difficult programming projects, decides to use a well-established design methodology. He asks for three more programmers. The team goes to work, making preliminary analyses, UML diagrams, meetings, Excel spreadsheets.&lt;/p&gt;

&lt;p&gt;At Consolidated, Charles spends time thinking about the problem. &lt;br&gt;
He often sits with his feet on the desk, scribbling on paper and drinking coffee. &lt;/p&gt;

&lt;h3&gt;
  
  
  Day 30
&lt;/h3&gt;

&lt;p&gt;At Automated, the team is starting to write code. The programmers are spending about half their time writing and building code, and the rest of their time in the conference, discussing the interfaces between the various modules. &lt;em&gt;They finally release an implementation schedule.&lt;/em&gt; In two months they will have a test version of the program. In four months they will have the gold version.&lt;/p&gt;

&lt;p&gt;Meanwhile, at Consolidated, Charles is busy coding.           &lt;/p&gt;

&lt;h3&gt;
  
  
  Day 90
&lt;/h3&gt;

&lt;p&gt;At Automated, the team has completed two of the four major modules required for their program. These modules are now under testing while the other modules are finished. When tested it seems to satisfy most of the original specifications. &lt;br&gt;
It has omitted one or two features and is very fussy about the format of its input data. However, the company decides to go with the program. They can always train their data-entry staff to enter data in the strict format required. The program is handed over to some maintenance programmers to eventually incorporate the missing features. &lt;/p&gt;

&lt;p&gt;Charles completes the project at Consolidated. When tested, the program does everything required in the specifications. Except for some quickly corrected oversights, it performs well. It even has a few additional convenience features which might significantly improve the usability of the program. &lt;/p&gt;

&lt;h3&gt;
  
  
  Aftermath
&lt;/h3&gt;

&lt;p&gt;Alan was complimented for completing his project on schedule. &lt;br&gt;
His manager at Automated looked over the program. He saw that the company standards were present. &lt;em&gt;He quickly gave up attempting to read the program however; it seemed quite incomprehensible.&lt;/em&gt; He was convinced the project was really much more complex than he had originally assumed. Alan was given a hefty pay raise and promoted as a reward for his achievement.&lt;/p&gt;

&lt;p&gt;At first Charles’ manager at Consolidated was impressed. But as he read through the source code, &lt;em&gt;seeing how simple it was, he was convinced that the project was really much simpler than he had originally thought.&lt;/em&gt; It seemed that this was not much of a challenge. At his next salary review, Charles was given a small raise. He was not given a promotion. After about a year he left the company.&lt;/p&gt;

&lt;p&gt;(An adaptation of &lt;a href="http://www.bruceblinn.com/parable.html"&gt;The Parable of the Two Programmers&lt;/a&gt;)&lt;/p&gt;

&lt;h2&gt;
  
  
  Who you are?
&lt;/h2&gt;

&lt;p&gt;Alan, who writes code that only he understands, but thus securing his job. Or Charles, who writes simple code, but is not appreciated because of this. I'll always be a Charles. Maybe just because the world is full of Alans.&lt;/p&gt;




&lt;p&gt;Thanks for reading. This article was originally posted on &lt;a href="https://www.raresportan.com/what-makes-good-code-good/"&gt;my blog&lt;/a&gt;.&lt;br&gt;
Cover Photo by Irvan Smith on Unsplash &lt;/p&gt;

</description>
      <category>craft</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
