<?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: Paulo Santos</title>
    <description>The latest articles on DEV Community by Paulo Santos (@gitpaulo).</description>
    <link>https://dev.to/gitpaulo</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F666129%2F9078036c-fc2c-4005-a3f5-466cf4957e0c.jpg</url>
      <title>DEV Community: Paulo Santos</title>
      <link>https://dev.to/gitpaulo</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/gitpaulo"/>
    <language>en</language>
    <item>
      <title>Reactive Programming 🌫️ - Demystified using RxJS</title>
      <dc:creator>Paulo Santos</dc:creator>
      <pubDate>Fri, 23 Jul 2021 22:38:48 +0000</pubDate>
      <link>https://dev.to/gitpaulo/reactive-programming-demystified-using-rxjs-53g5</link>
      <guid>https://dev.to/gitpaulo/reactive-programming-demystified-using-rxjs-53g5</guid>
      <description>&lt;p&gt;If you're looking for a RxJS quick start then this article is &lt;strong&gt;not&lt;/strong&gt; for you!&lt;/p&gt;

&lt;p&gt;Here, I will be tackling Reactive Programming with the goal of shedding some light over its unreasonably illusive world using RxJS as an example.&lt;/p&gt;

&lt;p&gt;I will be explaining the core Reactive Programming concepts, relating them to RxJS and how they work in practice. Hopefully, by the end of the read, you'll have a truer understanding of RxJS and should be able to quickly pick up any Rx Implementation to start coding with.&lt;/p&gt;

&lt;h2&gt;
  
  
  Statement
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;RxJS is an API for asynchronous programming&lt;br&gt;
with observable streams. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To understand what this means we need to define what is meant by &lt;em&gt;asynchronous programming&lt;/em&gt; and &lt;em&gt;observable streams&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;The best starting point can only be Reactive Programming itself!&lt;/p&gt;

&lt;h2&gt;
  
  
  Reactive Programming
&lt;/h2&gt;

&lt;p&gt;Reactive Programming (not to be confused with &lt;a href="http://conal.net/papers/icfp97/" rel="noopener noreferrer"&gt;Functional Reactive Programming&lt;/a&gt;!!) is a subset of &lt;strong&gt;Asynchronous Programming&lt;/strong&gt; and a paradigm where the availability of new information drives the logic forward rather than having control flow driven by a thread-of-execution.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Asynchronous Programming&lt;/strong&gt; is a means of parallel programming in which a unit of work runs separately from the main application thread. Generally, this is achieved via a messaging system where threads of execution competing for a shared resource don’t need to wait by blocking (preventing the thread of execution from performing other work until current work is done), and can as such perform other useful work while the resource is occupied. This concept is vital for Reactive Programming because it allows for non-blocking code to be written. Bellow a visualisation of the process:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4od7mbiuhm8joe78e9l2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4od7mbiuhm8joe78e9l2.png" alt="" width="675" height="600"&gt;&lt;/a&gt;&lt;a href="https://www.lightbend.com/white-papers-and-reports/reactive-programming-versus-reactive-systems" title="Async" rel="noopener noreferrer"&gt;&lt;/a&gt;&lt;/p&gt;&lt;a href="https://www.lightbend.com/white-papers-and-reports/reactive-programming-versus-reactive-systems" title="Async" rel="noopener noreferrer"&gt;Asynchronous Message System&lt;/a&gt;&lt;p&gt;&lt;/p&gt;

&lt;p&gt;Synchronous, blocking communication (left) is resource inefficient and easily bottlenecked. The Reactive approach (right) reduces risk, conserves valuable resources, and requires less hardware/infrastructure. &lt;/p&gt;

&lt;h3&gt;
  
  
  Messages vs Events
&lt;/h3&gt;

&lt;p&gt;Reactive Programming is generally Event-driven. &lt;strong&gt;Events are simply undirected messages&lt;/strong&gt;. At their core, they are (for all intents and purposes) an extension of an event. &lt;/p&gt;

&lt;p&gt;The Application Program Interface (API) for Reactive Programming libraries are generally either:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Callback-based:&lt;/strong&gt; where anonymous, side-effecting callbacks are attached to event sources and are being invoked when events pass through the dataflow chain.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Declarative:&lt;/strong&gt; through functional composition, usually using well-established combinators like map, filter, fold etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Reactive Systems
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.reactivemanifesto.org/" rel="noopener noreferrer"&gt;The Reactive Manifesto&lt;/a&gt; defines that reactive systems are: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Responsive:&lt;/strong&gt; responsive systems focus on providing rapid and consistent response times. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Resilient:&lt;/strong&gt; resilient systems handle problems as they occur and stay responsive in the face of failure.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Elastic:&lt;/strong&gt; elastic systems stays responsive under the varying workload and ergo have the ability to scale.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Message Driven:&lt;/strong&gt; message-driven systems rely on asynchronous message-passing to establish to ensure that change is propagated between components without interruptions.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx1thn17zb33wg7glzdvz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx1thn17zb33wg7glzdvz.png" alt="" width="800" height="303"&gt;&lt;/a&gt;&lt;a href="https://www.reactivemanifesto.org/" title="RM" rel="noopener noreferrer"&gt;&lt;/a&gt;&lt;/p&gt;&lt;a href="https://www.reactivemanifesto.org/" title="RM" rel="noopener noreferrer"&gt;Principles of Reactive Systems&lt;/a&gt;&lt;p&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Reactive Programming &amp;amp; Reactive Systems
&lt;/h3&gt;

&lt;p&gt;How do these two relate? In summary:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Reactive Programming&lt;/strong&gt; is a technique for managing internal logic and dataflow transformation within components of a system. It is a way of providing clarity, performance and resource efficiency of code.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reactive Systems&lt;/strong&gt; is a set of architectural principles. It puts emphasis on distributed communication and gives us tools to tackle resilience and elasticity in distributed systems.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Reactive Programming should be used as one of the tools to construct a Reactive System.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Defining the Paradigm in Practice
&lt;/h3&gt;

&lt;p&gt;Right, so, what is &lt;strong&gt;exactly&lt;/strong&gt; is Reactive Programming? There are &lt;em&gt;many&lt;/em&gt; definitions out there... some of which I think not even their authors understand what they mean. In the wise words of &lt;a href="https://twitter.com/andrestaltz" rel="noopener noreferrer"&gt;@andrestaltz&lt;/a&gt; - "Lets cut the bullshit"&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Reactive programming is programming with asynchronous data streams.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Beautiful, concise and above all explainable! In fact, this definition is almost the same as the statement about RxJS I presented before. That is because RxJS is within the Reactive Programming paradigm. &lt;/p&gt;

&lt;p&gt;From now on we assume Reactive programming &lt;strong&gt;with streams&lt;/strong&gt;. There are other types of implementations that can also be considered within the paradigm, such as: &lt;a href="https://en.wikipedia.org/wiki/Futures_and_promises" rel="noopener noreferrer"&gt;Promises/Futures&lt;/a&gt; and &lt;a href="https://en.wikipedia.org/wiki/Oz_(programming_language)#Dataflow_variables_and_declarative_concurrency" rel="noopener noreferrer"&gt;Dataflow variables&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Now, as promised, I'll be showing you guys what is meant by 'asynchronous data streams'.&lt;/p&gt;

&lt;h3&gt;
  
  
  Streams
&lt;/h3&gt;

&lt;p&gt;The key idea in Reactive Programming is that &lt;em&gt;everything&lt;/em&gt; (for the most part) can be a stream. Streams are &lt;strong&gt;cheap&lt;/strong&gt; and &lt;strong&gt;ubiquitous&lt;/strong&gt;. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A stream is a sequence of ongoing events ordered in time. It can only emit 3 things: a data typed value, an error, or a termination signal.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This definition is important to remember since it remains the same no matter the implementation of the paradigm.&lt;/p&gt;

&lt;p&gt;The way I like to think about streams is by visualising a water pipe with a closing mechanism where each water molecule (or set of) is an emitted value. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvk61sg0fug3pr8p00hh6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvk61sg0fug3pr8p00hh6.png" alt="" width="800" height="275"&gt;&lt;/a&gt;&lt;/p&gt;Water pipe stream analogy&lt;p&gt;&lt;/p&gt;

&lt;p&gt;The closing mechanism can be triggered manually by turning the tap, representing a termination signal, or implicitly, if the pipe fails to do its function, representing an error. A closed pipe can no longer push out water and we call it a completed stream.&lt;/p&gt;

&lt;p&gt;Now, let us focus on the first sentence of our definition: 'A stream is a sequence of &lt;strong&gt;ongoing events ordered in time&lt;/strong&gt;.' &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Febnd36etq6fzhutntpd5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Febnd36etq6fzhutntpd5.png" alt="" width="250" height="355"&gt;&lt;/a&gt;&lt;/p&gt;Capturing values analogy&lt;p&gt;&lt;/p&gt;

&lt;p&gt;In other words, water droplets (data) are being pushed out of the pipe (stream) as time (program execution) passes. How do we capture these droplets to act on them? &lt;/p&gt;

&lt;p&gt;In most implementations of Reactive Programming, we capture these emitted events only asynchronously, by defining functions that are called and passed one of the three appropriate outputs as a parameter:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;On value emission:&lt;/strong&gt; Each time a value is pushed through the stream it will be emitted and captured here. Can happen multiple times.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;On error emission:&lt;/strong&gt; When the stream error it will be captured here and the stream terminates. Happens only once.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;On termination:&lt;/strong&gt; When the stream is terminated it will be captured here. Happens only once.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That covers capturing. It's time to move into the manipulation of streams themselves. We do this via &lt;strong&gt;Operators&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Operators
&lt;/h3&gt;

&lt;p&gt;Operators offer a way to manipulate streams by transforming them. A transformation, in our context, is simply a function &lt;code&gt;f&lt;/code&gt; that maps a stream into another stream, i.e. &lt;code&gt;f: S1 → S2&lt;/code&gt; This function we call an operator.&lt;/p&gt;

&lt;p&gt;To visualise this simple imagine placing one or more appliances within the pipeline of our stream. These appliances could have filters in them or could modify the contents of the water (or other transformations) thereby transforming our stream into a new stream.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6f2qahx90sn2mflt3l2x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6f2qahx90sn2mflt3l2x.png" alt="" width="800" height="393"&gt;&lt;/a&gt;&lt;/p&gt;Water pipe stream analogy with operators &lt;p&gt;&lt;/p&gt;

&lt;p&gt;In the image above, our initial stream of type 'Unpurified Water' was transformed into a stream of type 'Purified Water' transforming the data that gets observed at the end of the pipeline from its original form.&lt;/p&gt;

&lt;p&gt;To explain operators and their effects on real streams of data we will have to dive into the world of Marble Diagrams.&lt;/p&gt;

&lt;h2&gt;
  
  
  Marble Diagrams
&lt;/h2&gt;

&lt;p&gt;Before explaining marble diagrams we need to improve our terminology a little bit.&lt;/p&gt;

&lt;h3&gt;
  
  
  Redefining Some Terms
&lt;/h3&gt;

&lt;p&gt;Now, because we will be dealing with ReactiveX in the next chapter, it's time to introduce some of the required terminologies. Don't worry, for now, I will only be giving abstracted definitions to a few terms that map to terms I've already covered. Below, the same diagrams as before, but with the new terminology included.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fth62dw2hw9o3p18cc9gr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fth62dw2hw9o3p18cc9gr.png" alt="" width="799" height="282"&gt;&lt;/a&gt;&lt;/p&gt;Water pipe stream analogy (w/terminology) &lt;p&gt;&lt;/p&gt;

&lt;p&gt;and for the operator diagram,&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1r9fgxt1yfyfp5mpv4v7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1r9fgxt1yfyfp5mpv4v7.png" alt="" width="799" height="407"&gt;&lt;/a&gt;&lt;/p&gt;Water pipe stream analogy with operators (w/terminology)  &lt;p&gt;&lt;/p&gt;

&lt;p&gt;Simple definitions for these terms are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Stream -&amp;gt; Observable:&lt;/strong&gt; A structure representing a stream of values over time.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tap -&amp;gt; Subscriber:&lt;/strong&gt; Sometimes called the consumer, the code that calls the subscription process on an observable structure.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Turning the tap -&amp;gt; Subscription:&lt;/strong&gt; The method that opens the stream for the observer.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Closing the tap -&amp;gt; Completing:&lt;/strong&gt; The action of marking the stream as completed meaning it is terminated.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bucket -&amp;gt; Observer:&lt;/strong&gt; The structure that captures our pushed values allowing us to act on them.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Appliances -&amp;gt; Operators:&lt;/strong&gt; Functions that transform the stream.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We will be returning to more precise definitions later since they are pretty much required to read any sort of RX documentation without inducing a headache. So don't worry if you don't quite understand what these mean yet.&lt;/p&gt;

&lt;p&gt;However, we will be using this new terminology from now on so I recommend keeping the term mapping in your head.&lt;/p&gt;

&lt;h3&gt;
  
  
  Marble Diagrams - The Observable
&lt;/h3&gt;

&lt;p&gt;Okay, time for actual marble diagrams! &lt;/p&gt;

&lt;p&gt;Learning Reactive Programming can be a daunting task so the Rx team came up with the concept of marble diagrams to help with visualising observables and their operators. These diagrams are incredibly intuitive and are commonly found in any Rx Operator documentation. They allow for an easy understanding of the operators without having to read much else. A good alternative to a chunky wall of text filled with terminology! I'll try to explain how to read them as best I can:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdki7ul5wpik316wkssw3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdki7ul5wpik316wkssw3.png" alt="" width="800" height="503"&gt;&lt;/a&gt;&lt;a href="https://medium.com/@bencabanes/marble-testing-observable-introduction-1f5ad39231c" title="OMD" rel="noopener noreferrer"&gt;&lt;/a&gt;&lt;/p&gt;&lt;a href="https://medium.com/@bencabanes/marble-testing-observable-introduction-1f5ad39231c" title="OMD" rel="noopener noreferrer"&gt;Overview of a Marble Diagram&lt;/a&gt;  &lt;p&gt;&lt;/p&gt;

&lt;p&gt;Okay... my bad haha, sorry! Let's go step by step. &lt;/p&gt;

&lt;p&gt;Marble diagrams describe observables. Observables are streams of values through time. So, we need a time axis!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fue48ew05m7wpr9sgwqgv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fue48ew05m7wpr9sgwqgv.png" alt="" width="600" height="200"&gt;&lt;/a&gt;&lt;a href="https://www.zachgollwitzer.com/posts/2020/rxjs-marble-diagram/" title="OMD" rel="noopener noreferrer"&gt;&lt;/a&gt;&lt;/p&gt;&lt;a href="https://www.zachgollwitzer.com/posts/2020/rxjs-marble-diagram/" title="OMD" rel="noopener noreferrer"&gt;Marble Diagram: time axis&lt;/a&gt;  &lt;p&gt;&lt;/p&gt;

&lt;p&gt;Now that we have a time axis we need to represent our observable outputs. If you recall our earlier definition, an observable can only output a value, a termination signal or an error. &lt;/p&gt;

&lt;p&gt;Let's start with the easy one, the termination signal:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe9afmw9ld3xyevxd079m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe9afmw9ld3xyevxd079m.png" alt="" width="600" height="200"&gt;&lt;/a&gt;&lt;a href="https://www.zachgollwitzer.com/posts/2020/rxjs-marble-diagram/" title="OMD" rel="noopener noreferrer"&gt;&lt;/a&gt;&lt;/p&gt;&lt;a href="https://www.zachgollwitzer.com/posts/2020/rxjs-marble-diagram/" title="OMD" rel="noopener noreferrer"&gt;Marble Diagram: termination signal&lt;/a&gt;   &lt;p&gt;&lt;/p&gt;

&lt;p&gt;In similar fashion, we have our error output:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fci83oemg1ho6pztolb9p.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fci83oemg1ho6pztolb9p.png" alt="" width="600" height="200"&gt;&lt;/a&gt;&lt;a href="https://www.zachgollwitzer.com/posts/2020/rxjs-marble-diagram/" title="OMD" rel="noopener noreferrer"&gt;&lt;/a&gt;&lt;/p&gt;&lt;a href="https://www.zachgollwitzer.com/posts/2020/rxjs-marble-diagram/" title="OMD" rel="noopener noreferrer"&gt;Marble Diagram: error&lt;/a&gt;   &lt;p&gt;&lt;/p&gt;

&lt;p&gt;Finally, lets represent our emitted value:  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqzuzc29irqvf2hy8l3w9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqzuzc29irqvf2hy8l3w9.png" alt="" width="600" height="200"&gt;&lt;/a&gt;&lt;a href="https://www.zachgollwitzer.com/posts/2020/rxjs-marble-diagram/" title="OMD" rel="noopener noreferrer"&gt;&lt;/a&gt;&lt;/p&gt;&lt;a href="https://www.zachgollwitzer.com/posts/2020/rxjs-marble-diagram/" title="OMD" rel="noopener noreferrer"&gt;Marble Diagram: value push/emission&lt;/a&gt;   &lt;p&gt;&lt;/p&gt;

&lt;p&gt;There can be multiple values across the time axis as long as there is no termination or error output behind them as those will unsubscribe from the observable.&lt;/p&gt;

&lt;p&gt;Done, simple right? On to the next part: operators in marble diagrams!&lt;/p&gt;

&lt;h3&gt;
  
  
  Marble Diagrams - The Operators
&lt;/h3&gt;

&lt;p&gt;As previously mentioned, operators are functions that transform observables. That means they take as input one or more observables and output a new observable. We can represent them in a marble diagram like so:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxab3a7gqc9mm0xl4nom7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxab3a7gqc9mm0xl4nom7.png" alt="" width="799" height="227"&gt;&lt;/a&gt;&lt;/p&gt;Marble diagram of a filter operator   &lt;p&gt;&lt;/p&gt;

&lt;p&gt;The block in between is our operator function, taking in an observable and returning another. So, our function is filtering the input observable by taking the modulus 2 to determine whether a pushed value is even and if it is it allows that push value to pass through, essentially, filtering the stream. &lt;/p&gt;

&lt;p&gt;As mentioned before, operators can have more than one observable as input, such as the case for operators such as &lt;code&gt;switchMap&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F76qz9j0n1ggp30s8mcy9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F76qz9j0n1ggp30s8mcy9.png" alt="" width="800" height="376"&gt;&lt;/a&gt;&lt;/p&gt;Marble diagram of a switch map operator     &lt;p&gt;&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;switchMap&lt;/code&gt; operator is a very popular one that has a handful of practical applications. It is generally used to implement a discard action between the input streams which can save a lot of trouble and computation in practice.&lt;/p&gt;

&lt;p&gt;In summary, every time the &lt;code&gt;Input Observable 1&lt;/code&gt; emits a value, &lt;code&gt;Input Observable 2&lt;/code&gt; emits all of its values unless &lt;code&gt;Input Observable 1&lt;/code&gt; emits a new value before the &lt;code&gt;Input Observable 2&lt;/code&gt; completes. If you look at the output observable you will notice that there are only two 30's. This is because &lt;code&gt;Input Observable 2&lt;/code&gt; could not be complete before &lt;code&gt;Input Observable 1&lt;/code&gt; emitted the value 5. You easily confirm this because the space between 3 and 5 is much less than the size of the axis for &lt;code&gt;Input Observable 2&lt;/code&gt;, suggesting there was only time to emit the first two values. &lt;/p&gt;

&lt;h2&gt;
  
  
  In Practice - RxJS
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Overview of RxJS
&lt;/h3&gt;

&lt;p&gt;RxJS is a library extending &lt;a href="http://reactivex.io/" rel="noopener noreferrer"&gt;ReactiveX&lt;/a&gt; for composing asynchronous and event-based programs by using observable sequences with JavaScript. It provides one core type, the Observable, satellite types (Observer, Schedulers, Subjects) and operators (map, filter, reduce, every, etc) to allow the manipulation of the observable streams with easy and significantly reducing the amount of code needed to solve asynchronous problems. &lt;/p&gt;

&lt;h3&gt;
  
  
  Advantages VS Disadvantages
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Advantages​
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Growing very rapidly.​

&lt;ul&gt;
&lt;li&gt;RxJs alone has 25mil weekly downloads.​&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Provides a very high-quality asynchronous API.​&lt;/li&gt;
&lt;li&gt;Lightweight &amp;amp; memory optimised.​&lt;/li&gt;
&lt;li&gt;Easy error handling.​&lt;/li&gt;
&lt;li&gt;Makes asynchronous programming much faster in most applications.​&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;
  
  
  Disadvantages​
&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;Relatively steep learning curve.​&lt;/li&gt;
&lt;li&gt;Implies a functional programming style (data immutability).​&lt;/li&gt;
&lt;li&gt;Testing/debugging can be a learning process.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  RxJS Glossary
&lt;/h3&gt;

&lt;p&gt;In RxJS some arguably established definitions are:&lt;/p&gt;

&lt;h4&gt;
  
  
  Entities
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Observable:&lt;/strong&gt; represents the idea of an invokable collection of future values or events.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Observer:&lt;/strong&gt; is a collection of callbacks that knows how to listen to values delivered by the Observable.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Subscription:&lt;/strong&gt; represents the execution of an Observable, which is primarily useful for cancelling the execution.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Operators:&lt;/strong&gt; are pure functions that enable a functional programming style of dealing with collections with operations like map, filter, concat, reduce, etc.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Subject:&lt;/strong&gt; is equivalent to an EventEmitter, and the only way of multicasting a value or event to multiple Observers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Schedulers:&lt;/strong&gt; are centralized dispatchers to control concurrency, allowing us to coordinate when computation happens on e.g. setTimeout or requestAnimationFrame or others.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Producer:&lt;/strong&gt; The code that is subscribing to the observable. This is whoever is being notified of nexted values, and errors or completions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Consumer:&lt;/strong&gt; Any system or thing that is the source of values that are being pushed out of the observable subscription to the consumer. &lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Concepts
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Unicast:&lt;/strong&gt; The act of one producer being observed only one consumer. An observable is "unicast" when it only connects one producer to one consumer. Unicast doesn't necessarily mean "cold".&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multicast&lt;/strong&gt;: The act of one producer being observed by many consumers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cold&lt;/strong&gt;: An observable is "cold" when it creates a new producer during subscribe for every new subscription. As a result, a "cold" observables are always unicast, being one producer observed by one consumer. Cold observables can be made hot but not the other way around.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hot&lt;/strong&gt;: An observable is "hot", when its producer was created outside of the context of the subscribe action. This means that the "hot" observable is almost always multicast. It is possible that a "hot" observable is still technically unicast if it is engineered to only allow one subscription at a time, however, there is no straightforward mechanism for this in RxJS, and the scenario is unlikely. For the purposes of discussion, all "hot" observables can be assumed to be multicast. Hot observables cannot be made cold.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Push&lt;/strong&gt;: Observables are a push-based type. That means rather than having the consumer call a function or perform some other action to get a value, the consumer receives values as soon as the producer has produced them, via a registered next handler.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pull&lt;/strong&gt;: Pull-based systems are the opposite of push-based. In a pull-based type or system, the consumer must request each value the producer has produced manually, perhaps long after the producer has actually done so. Examples of such systems are Functions and Iterators&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Observables &amp;amp; Subscriptions
&lt;/h3&gt;

&lt;p&gt;By now we should agree that observables are simply structures that lazy push collections of multiple values. Subscriptions are the resulting structure representing a disposable resource, usually the execution of an Observable.&lt;/p&gt;

&lt;p&gt;Heres how we code them in RxJS:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Observable&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;rxjs&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="cm"&gt;/* Instantiate an observable */&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;observable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Observable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;subscriber&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;subscriber&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// pushes a value&lt;/span&gt;
  &lt;span class="nx"&gt;subscriber&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// pushes another value synchronously&lt;/span&gt;
  &lt;span class="nf"&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;subscriber&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// pushes last value after a wait of 1s&lt;/span&gt;
    &lt;span class="nx"&gt;subscriber&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;complete&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// terminates observable stream&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="cm"&gt;/* Subscribing to an observable */&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&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;just before subscribe&lt;/span&gt;&lt;span class="dl"&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;subscription&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;observable&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="c1"&gt;// The three possible output captures:&lt;/span&gt;
  &lt;span class="nf"&gt;next&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="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="nf"&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;got value &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="nf"&gt;error&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="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&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;something wrong occurred: &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&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="nf"&gt;complete&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="nf"&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;done&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="p"&gt;});&lt;/span&gt; &lt;span class="c1"&gt;// creates subscription object&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&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;just after subscribe&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="cm"&gt;/* Unsubscribing to an observable using subscription */&lt;/span&gt;
&lt;span class="nf"&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;subscription&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;unsubscribe&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Logs:&lt;/span&gt;
&lt;span class="c1"&gt;// just before subscribe &lt;/span&gt;
&lt;span class="c1"&gt;// got value 1 &lt;/span&gt;
&lt;span class="c1"&gt;// got value 2 &lt;/span&gt;
&lt;span class="c1"&gt;// just after subscribe &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice how we never see the value 3 logged because we cancel our subscription before it is emitted through the closure function passed to &lt;code&gt;setTimeout&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;However, this does not mean the value was not emitted, it was, we just don't see it because we stopped subscribing. The stream was not terminated via the act of unsubscribing.&lt;/p&gt;

&lt;h3&gt;
  
  
  Hot vs Cold Observables
&lt;/h3&gt;

&lt;p&gt;A &lt;strong&gt;cold observable&lt;/strong&gt; starts producing data when some code invokes a &lt;strong&gt;subscribe()&lt;/strong&gt; function on it.&lt;/p&gt;

&lt;p&gt;A cold observable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Observable&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;rxjs&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Creating a cold observable&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;observable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Observable&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;observer&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;observer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;random&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// We explicitly push the value to the stream&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Subscription 1&lt;/span&gt;
&lt;span class="nx"&gt;observable&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;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="nf"&gt;log&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;// 0.24957144215097515 (random number)&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Subscription 2&lt;/span&gt;
&lt;span class="nx"&gt;observable&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;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="nf"&gt;log&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;// 0.004617340049055896 (random number)&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A &lt;strong&gt;hot observable&lt;/strong&gt; produces data even if &lt;strong&gt;no subscribers are interested&lt;/strong&gt; in the data.&lt;/p&gt;

&lt;p&gt;A hot observable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Observable&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;rxjs&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Coming from an event which is constantly emmit values&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;observable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Observable&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fromEvent&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;click&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Subscription 1&lt;/span&gt;
&lt;span class="nx"&gt;observable&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;event&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;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;clientX&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// x position of click&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Subscription 2&lt;/span&gt;
&lt;span class="nx"&gt;observable&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;event&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;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;clientY&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// y position of click&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Promises vs Observables
&lt;/h3&gt;

&lt;p&gt;The main differences are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Promises are eager. Observables are lazy.​&lt;/li&gt;
&lt;li&gt;Promises are single-value emissions. Observables are multi-value streams.​&lt;/li&gt;
&lt;li&gt;Promises have no cancelling or operator APIs. Observables do.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgbg528g59fb2w50vclj0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgbg528g59fb2w50vclj0.png" alt="" width="800" height="371"&gt;&lt;/a&gt;&lt;/p&gt;Promise vs Observable   &lt;p&gt;&lt;/p&gt;

&lt;p&gt;A stackblitz example of RxJS vs Promises: &lt;a href="https://stackblitz.com/edit/classicjs-vs-rxjs" rel="noopener noreferrer"&gt;https://stackblitz.com/edit/classicjs-vs-rxjs&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Observables can be Promises
&lt;/h4&gt;

&lt;p&gt;Although observables are not an extension of the &lt;a href="https://promisesaplus.com/" rel="noopener noreferrer"&gt;Promise/A+&lt;/a&gt; specification, RxJS still provides means to transform an observable into a true Promise. An example follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Observable&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;rxjs&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Return a basic observable&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;simpleObservable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;val&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;Observable&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;of&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;val&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;delay&lt;/span&gt;&lt;span class="p"&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;// Convert basic observable to promise&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;example&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;sample&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;First Example&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="nf"&gt;toPromise&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// Now its a promise&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&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;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&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;From Promise:&lt;/span&gt;&lt;span class="dl"&gt;'&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="c1"&gt;// After 500ms, output 'First Example'&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With the use of RxJS's &lt;code&gt;toPromise&lt;/code&gt; method, any observable can be converted to a promise. Note that because it returns a true JS Promise, &lt;code&gt;toPromise&lt;/code&gt; is not a pipable operator, as it does not return an observable.&lt;/p&gt;

&lt;h3&gt;
  
  
  Observer
&lt;/h3&gt;

&lt;p&gt;In practice, an Observer is a consumer of values delivered by an Observable. Observers are simply a set of callbacks, one for each type of notification delivered by the Observable: &lt;code&gt;next&lt;/code&gt;, &lt;code&gt;error&lt;/code&gt;, and &lt;code&gt;complete&lt;/code&gt;. The following is an example of a typical Observer object:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;observer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;next&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&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;Observer got a next value: &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&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;Observer got an error: &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="na"&gt;complete&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;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&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;Observer got a complete notification&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="c1"&gt;// To use it, pass it to a subscribe&lt;/span&gt;
&lt;span class="nx"&gt;observable&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;observer&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it for observers, really!&lt;/p&gt;

&lt;h3&gt;
  
  
  Operators
&lt;/h3&gt;

&lt;p&gt;RxJS is mostly useful for its operators, even though the Observable is the foundation. Previously we studied operators as functions that transformed streams. Nothing changes here, just terminology!&lt;/p&gt;

&lt;p&gt;RxJS has a (very) vast library of operators. We will only be touching on a few simple ones to cover what we've talked about already:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;rxjs&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;filter&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;rxjs/operators&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;]).&lt;/span&gt;&lt;span class="nf"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nf"&gt;filter&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&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="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;subscribe&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="c1"&gt;// [2, 4]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3fy4d0lg6i6a3c5fx4xb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3fy4d0lg6i6a3c5fx4xb.png" alt="image" width="800" height="338"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;If you remember our filter example from before this should be fairly simple to understand!&lt;/p&gt;

&lt;h3&gt;
  
  
  Pipeline
&lt;/h3&gt;

&lt;p&gt;A pipeline is simply a series of operators that get executed in order. Something obvious but that people forget, every pipeline operator &lt;strong&gt;must&lt;/strong&gt; return an observable.&lt;/p&gt;

&lt;p&gt;The same exmaple as before but with chaining operators:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;rxjs&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;take&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;map&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;rxjs/operators&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;]).&lt;/span&gt;&lt;span class="nf"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nf"&gt;filter&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&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="nf"&gt;take&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;firstValue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;The first even number was &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;firstValue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;subscribe&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are a ton more operators that do vastly different things in categories such as: Creation, Filtering, Combination, Error Handling, Transformation, Multicasting, etc. I encourage you to try a few from each of the categories out. This is the power of RxJS, there's a lot already done for you!&lt;/p&gt;

&lt;h3&gt;
  
  
  Subjects
&lt;/h3&gt;

&lt;p&gt;A Subject is like an Observable, but can multicast to many Observers. Subjects are like EventEmitters: they maintain a registry of many listeners. In fact, part of a subject is literally an observable and you can get a reference to that observable. &lt;/p&gt;

&lt;p&gt;The easiest way to think of a subject is quite literally:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Subject = Observer + Observable&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Subject&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;rxjs&lt;/span&gt;&lt;span class="dl"&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;subject&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;Subject&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;number&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;subject&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;next&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;v&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;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`observerA: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;v&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="p"&gt;});&lt;/span&gt;
&lt;span class="nx"&gt;subject&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;next&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;v&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;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`observerB: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;v&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="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;subject&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;subject&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Logs:&lt;/span&gt;
&lt;span class="c1"&gt;// observerA: 1&lt;/span&gt;
&lt;span class="c1"&gt;// observerB: 1&lt;/span&gt;
&lt;span class="c1"&gt;// observerA: 2&lt;/span&gt;
&lt;span class="c1"&gt;// observerB: 2&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;observable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

&lt;span class="nx"&gt;observable&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;subject&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// You can subscribe providing a Subject&lt;/span&gt;

&lt;span class="c1"&gt;// Logs:&lt;/span&gt;
&lt;span class="c1"&gt;// observerA: 1&lt;/span&gt;
&lt;span class="c1"&gt;// observerB: 1&lt;/span&gt;
&lt;span class="c1"&gt;// observerA: 2&lt;/span&gt;
&lt;span class="c1"&gt;// observerB: 2&lt;/span&gt;
&lt;span class="c1"&gt;// observerA: 3&lt;/span&gt;
&lt;span class="c1"&gt;// observerB: 3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;IMO, the best use case for Subjects is when the code it is referenced in is the one that is producing the observable data. You can easily let your consumers subscribe to the Subject and then call the &lt;code&gt;.next()&lt;/code&gt; function to push data into the pipeline. Be wary of overusing them since most problems are solvable with only data transformation and Observables.&lt;/p&gt;

&lt;h3&gt;
  
  
  Schedulers
&lt;/h3&gt;

&lt;p&gt;Finally, schedulers! They might seem hard to understand but are quite simple at a surface level which is more than enough for us to know about. In essence, schedulers control the order of tasks for Observables. There are only a few of them and they won't be changing anytime soon, here they are:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0iuxaq13i0seumfqvsv0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0iuxaq13i0seumfqvsv0.png" alt="" width="789" height="282"&gt;&lt;/a&gt;&lt;/p&gt;Table of the types of schedulers   &lt;p&gt;&lt;/p&gt;

&lt;p&gt;You can use schedulers by passing them to observables through a handful of operators (usually of the creation category) as arguments. The most basic example, forcing a synchronous observable to behave asynchronously:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Observable&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;asyncScheduler&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;rxjs&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;observeOn&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;rxjs/operators&lt;/span&gt;&lt;span class="dl"&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;observable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Observable&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;observer&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;observer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;observer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;observer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;observer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;complete&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nf"&gt;observeOn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;asyncScheduler&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="nf"&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;just before subscribe&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;observable&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="nf"&gt;next&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="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="nf"&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;got value &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="nf"&gt;error&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="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&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;something wrong occurred: &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&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="nf"&gt;complete&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="nf"&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;done&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="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="nf"&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;just after subscribe&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Logs&lt;/span&gt;
&lt;span class="c1"&gt;// just before subscribe&lt;/span&gt;
&lt;span class="c1"&gt;// just after subscribe&lt;/span&gt;
&lt;span class="c1"&gt;// got value 1&lt;/span&gt;
&lt;span class="c1"&gt;// got value 2&lt;/span&gt;
&lt;span class="c1"&gt;// got value 3&lt;/span&gt;
&lt;span class="c1"&gt;// done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice how the notifications got &lt;code&gt;value...&lt;/code&gt; were delivered after just after subscription. This is because &lt;code&gt;observeOn(asyncScheduler)&lt;/code&gt; introduces a proxy Observer between the new Observable and the final Observer. &lt;/p&gt;

&lt;p&gt;Other schedulers can be used for different timings. We are done!&lt;/p&gt;

&lt;h3&gt;
  
  
  Amazing RxJS Resources
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;RxJS visualizer:&lt;/strong&gt; &lt;a href="https://rxviz.com/" rel="noopener noreferrer"&gt;https://rxviz.com/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Instant marble diagrams:&lt;/strong&gt; &lt;a href="https://thinkrx.io/" rel="noopener noreferrer"&gt;https://thinkrx.io/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Docs with marble diagrams:&lt;/strong&gt; &lt;a href="https://rxmarbles.com/" rel="noopener noreferrer"&gt;https://rxmarbles.com/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Operator decision tree:&lt;/strong&gt; &lt;a href="https://rxjs.dev/operator-decision-tree" rel="noopener noreferrer"&gt;https://rxjs.dev/operator-decision-tree&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Reference
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://gist.github.com/staltz/868e7e9bc2a7b8c1f754" rel="noopener noreferrer"&gt;https://gist.github.com/staltz/868e7e9bc2a7b8c1f754&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.reactivemanifesto.org/" rel="noopener noreferrer"&gt;https://www.reactivemanifesto.org/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/Reactive_programming" rel="noopener noreferrer"&gt;https://en.wikipedia.org/wiki/Reactive_programming&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.zachgollwitzer.com/posts/2020/rxjs-marble-diagram/" rel="noopener noreferrer"&gt;https://www.zachgollwitzer.com/posts/2020/rxjs-marble-diagram/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/@bencabanes/marble-testing-observable-introduction-1f5ad39231c" rel="noopener noreferrer"&gt;https://medium.com/@bencabanes/marble-testing-observable-introduction-1f5ad39231c&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.lightbend.com/white-papers-and-reports/reactive-programming-versus-reactive-systems" rel="noopener noreferrer"&gt;https://www.lightbend.com/white-papers-and-reports/reactive-programming-versus-reactive-systems&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>reactive</category>
      <category>rxjs</category>
    </item>
    <item>
      <title>Journey of a web page 🛣️ - How browsers work</title>
      <dc:creator>Paulo Santos</dc:creator>
      <pubDate>Mon, 19 Jul 2021 09:04:55 +0000</pubDate>
      <link>https://dev.to/gitpaulo/journey-of-a-web-page-how-browsers-work-10co</link>
      <guid>https://dev.to/gitpaulo/journey-of-a-web-page-how-browsers-work-10co</guid>
      <description>&lt;p&gt;This article covers the processes that happen in-between a user entering a web address in a browser and a web page showing up as a result.&lt;/p&gt;

&lt;h2&gt;
  
  
  Overview
&lt;/h2&gt;

&lt;p&gt;There are a handful of steps that occur betiwx the time a user requests a web page and the time it displays in their browser. To better cover each of them, I've divided those steps into the following sections:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Navigation&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Resolving the web address (DNS Lookup)&lt;/li&gt;
&lt;li&gt;Establishing a connection to the server (TCP 3-way handshake)&lt;/li&gt;
&lt;li&gt;Establishing a security protocol (TLS negotiation)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fetching&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Browser Caching&lt;/li&gt;
&lt;li&gt;HTTP request&lt;/li&gt;
&lt;li&gt;HTTP response&lt;/li&gt;
&lt;li&gt;Streaming and Progressive Parsing&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Parsing&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Building the DOM tree&lt;/li&gt;
&lt;li&gt;Building the CSSOM tree&lt;/li&gt;
&lt;li&gt;Combining the trees into the render tree&lt;/li&gt;
&lt;li&gt;Preload Scanner&lt;/li&gt;
&lt;li&gt;JavaScript Compilation&lt;/li&gt;
&lt;li&gt;Building the Accessibility Tree&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rendering&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Critical Rendering Path&lt;/li&gt;
&lt;li&gt;Layout&lt;/li&gt;
&lt;li&gt;Paint&lt;/li&gt;
&lt;li&gt;Compositing&lt;/li&gt;
&lt;li&gt;Dynamic Rendering and Updates&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Finalising&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;JavaScript Occupied.&lt;/li&gt;
&lt;li&gt;Document Lifecycle Events&lt;/li&gt;
&lt;li&gt;User can now browse the page!&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Use this index to jump to any particular section of interest. If you're new to some of these concepts, I suggest a linear read.&lt;/p&gt;

&lt;p&gt;It is worth noting that browsers perform many of these steps concurrently, and some may be skipped entirely thanks to caching or connection reuse. For simplicity, we'll follow the general journey of a page from navigation to rendering.&lt;/p&gt;

&lt;p&gt;It is time for a quick background lesson!&lt;/p&gt;

&lt;h2&gt;
  
  
  Background
&lt;/h2&gt;

&lt;p&gt;This section contains a very &lt;em&gt;quick&lt;/em&gt; and &lt;em&gt;general&lt;/em&gt; overview of the some of the core background concepts that are required to understand the later parts of the article.&lt;/p&gt;

&lt;h3&gt;
  
  
  Networking models
&lt;/h3&gt;

&lt;p&gt;Models exist to explain how data is transmitted through a network. In particular, there exists a network model so widely known that even those that do not partake in &lt;em&gt;hackerman&lt;/em&gt; things might've heard of! We call it the Open Systems Interconnected (OSI) model.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsx08iepkwc18o55nwx9s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsx08iepkwc18o55nwx9s.png" alt="The OSI Model" width="710" height="722"&gt;&lt;/a&gt;&lt;a href="https://community.fs.com/blog/tcpip-vs-osi-whats-the-difference-between-the-two-models.html" title="foo" rel="noopener noreferrer"&gt;&lt;/a&gt;&lt;/p&gt;&lt;a href="https://community.fs.com/blog/tcpip-vs-osi-whats-the-difference-between-the-two-models.html" title="foo" rel="noopener noreferrer"&gt;The OSI Model&lt;/a&gt;&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.iso.org/ics/35.100/x/" rel="noopener noreferrer"&gt;The Open Systems Interconnection (OSI) model&lt;/a&gt; describes seven layers that computer systems use to communicate over a network. Each upper layer is one level of abstraction higher than the previous, all the way up to the application (browser) layer which we will be talking about.&lt;/p&gt;

&lt;p&gt;It’s important to understand that the OSI model is a “conceptual model” for how applications communicate over a network. It is &lt;strong&gt;not&lt;/strong&gt; a protocol. Do not get the two confused. Protocols are strict sets of rules that may live within these layers.&lt;/p&gt;

&lt;p&gt;An older and very similar model, possibly more relevant towards the article, is the &lt;a href="https://en.wikipedia.org/wiki/Internet_protocol_suite" rel="noopener noreferrer"&gt;TCP/IP model&lt;/a&gt;. This network model is used for both modelling current Internet architecture and providing a set of rules (concrete protocols) that are followed by all forms of transmission over that network.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd4qicoy7basi6gd4joxr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd4qicoy7basi6gd4joxr.png" alt="" width="710" height="450"&gt;&lt;/a&gt;&lt;a href="https://community.fs.com/blog/tcpip-vs-osi-whats-the-difference-between-the-two-models.html" title="OSI vs TCP/IP" rel="noopener noreferrer"&gt;&lt;/a&gt;&lt;/p&gt;&lt;a href="https://community.fs.com/blog/tcpip-vs-osi-whats-the-difference-between-the-two-models.html" title="OSI vs TCP/IP" rel="noopener noreferrer"&gt;OSI vs TCP/IP&lt;/a&gt;&lt;p&gt;&lt;/p&gt;

&lt;p&gt;I will be using and referring to this model with its associated protocols throughout the article.&lt;/p&gt;

&lt;p&gt;Any data sent from an application to another will have to travel up and down through these layers a few numbers of times (depending on how many middlemen there are). Of course, this happens incredibly fast nowadays, however, it still does happen and understanding the overview of the process is something that every developer should know. The following is an image representation of network process between a server and a client application:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F24o98vnamwefnr850216.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F24o98vnamwefnr850216.png" alt="" width="710" height="440"&gt;&lt;/a&gt;&lt;a href="https://community.fs.com/blog/tcpip-vs-osi-whats-the-difference-between-the-two-models.html" title="TCP/IP data travel" rel="noopener noreferrer"&gt;&lt;/a&gt;&lt;/p&gt;&lt;a href="https://community.fs.com/blog/tcpip-vs-osi-whats-the-difference-between-the-two-models.html" title="TCP/IP data travel" rel="noopener noreferrer"&gt;TCP/IP model data path between applications&lt;/a&gt;&lt;p&gt;&lt;/p&gt;

&lt;p&gt;Take this example - a user requesting to browse a page using their browser: &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The request is first sent to the application layer, where it is processed from layer to layer down with each layer performing its designated functions. &lt;/li&gt;
&lt;li&gt;The data is then transmitted over the physical layer of the network until the destination server or another device receives it. &lt;/li&gt;
&lt;li&gt;At this point the data is passed up through the layers again, each layer performing its assigned operations until the data is used by the web server software. &lt;/li&gt;
&lt;li&gt;This process is repeated again for the response of the server. &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In general, this is how machines communicate over the network!&lt;/p&gt;

&lt;h3&gt;
  
  
  High-level abstraction of a browser
&lt;/h3&gt;

&lt;p&gt;The later sections of the article will be covering how a typical browser displays the content of a page on screen. A high-level understanding of the browser is important when reading those sections. I will be referencing some of the following browser components:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;The user interface:&lt;/strong&gt; this includes the address bar, back/forward button, bookmarking menu, etc. Every part of the browser display except the window where you see the requested page.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The browser engine:&lt;/strong&gt; marshals actions between the UI and the rendering engine.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The rendering engine:&lt;/strong&gt; responsible for displaying requested content. For example, if the requested content is HTML, the rendering engine parses HTML and CSS and displays the parsed content on the screen.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Networking:&lt;/strong&gt; for network calls such as HTTP requests, using different implementations for different platforms behind a platform-independent interface.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;UI backend:&lt;/strong&gt; used for drawing basic widgets like combo boxes and windows. This backend exposes a generic interface that is not platform-specific. Underneath it uses operating system user interface methods.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;JavaScript interpreter:&lt;/strong&gt; Used to parse and execute JavaScript code.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data storage:&lt;/strong&gt; This is a persistence layer. The browser may need to save all sorts of data locally, such as cookies. Browsers also support storage mechanisms such as localStorage, IndexedDB, WebSQL and FileSystem.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fivei7zfohim9n6l83bbk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fivei7zfohim9n6l83bbk.png" alt="" width="500" height="339"&gt;&lt;/a&gt;&lt;a href="https://www.html5rocks.com/en/tutorials/internals/howbrowserswork/" title="Browser Components" rel="noopener noreferrer"&gt;&lt;/a&gt;&lt;/p&gt;&lt;a href="https://www.html5rocks.com/en/tutorials/internals/howbrowserswork/" title="Browser Components" rel="noopener noreferrer"&gt;Browser Components&lt;/a&gt;&lt;p&gt;&lt;/p&gt;

&lt;p&gt;It is important to note that browsers such as Chrome have a multi-process approach for performance and security reasons. This means that they run instances of some of these components, such as the rendering engine, in separate processes. A tab is not necessarily a single process: Chrome may use multiple renderer processes within a tab, or share one across tabs. You can see this by checking Chrome's processes in its Task Manager.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwv6sub7wk7fxyi25j1yh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwv6sub7wk7fxyi25j1yh.png" alt="" width="650" height="385"&gt;&lt;/a&gt;&lt;/p&gt;Screenshot of Chrome's Task Manager&lt;p&gt;&lt;/p&gt;

&lt;p&gt;As you can observe from the screenshot above, Chrome's Task Manager shows separate tasks with CPU/Network/GPU statistics. Some of these correspond to renderer processes, while others belong to shared browser services. You can further confirm this by listing your OS's processes.&lt;/p&gt;

&lt;p&gt;To conclude this background section, it is important to note that what you just read so far is a &lt;strong&gt;very&lt;/strong&gt; high-level generalisation and abstraction of how networks and browsers actually work. Not all networks strictly abide by the OSI/TCP IP models and the main browsers in use today are all different in their own ways but share a common base of concepts that allows us to abstract them to what you've just read. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;For browsers, as an example, they all follow (to some degree) the specifications maintained by the &lt;a href="https://www.w3.org/" rel="noopener noreferrer"&gt;W3C (World Wide Web Consortium) organization&lt;/a&gt;, which is the standards organization for the web. However, the actual implementation of each component varies quite significantly. e.g. rendering engines are different, Internet Explorer uses Trident, Firefox uses Gecko, Safari uses WebKit. Chrome, Edge and Opera use Blink, a fork of WebKit etc. And the same goes for javascript engine pipelines!&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Journey of a page
&lt;/h2&gt;

&lt;p&gt;You open up a browser and type in &lt;a href="http://www.google.com" rel="noopener noreferrer"&gt;www.google.com&lt;/a&gt;. This is what happens.&lt;/p&gt;

&lt;h3&gt;
  
  
  Navigation
&lt;/h3&gt;

&lt;p&gt;The first step is navigating to the correct place. Navigating to a web page is finding where the assets for that page are located. To us, web pages are simply domain names, but to computers, they resolve into IP addresses.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3l0quvd7dcsg97hbfmfu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3l0quvd7dcsg97hbfmfu.png" alt="" width="630" height="172"&gt;&lt;/a&gt;www.google.com, the page resources will be located on servers reachable through the IP addresses returned by DNS. If the address is not already cached, a Domain Name System (DNS) lookup is usually required.&lt;/p&gt;

&lt;h5&gt;
  
  
  Round Trip Time
&lt;/h5&gt;

&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Round-trip_delay" rel="noopener noreferrer"&gt;Round-trip time (RTT)&lt;/a&gt; is the duration, measured in milliseconds, from when a browser sends a request to when it receives a response from a server. It's a key performance metric for web applications and one of the main factors, along with &lt;a href="https://developer.mozilla.org/en-US/docs/Glossary/time_to_first_byte" rel="noopener noreferrer"&gt;Time to First Byte (TTFB)&lt;/a&gt;, when measuring page load time and network latency.&lt;/p&gt;

&lt;p&gt;I will be annotating each network process with their corresponding RTT.&lt;/p&gt;

&lt;h4&gt;
  
  
  Resolving a web address - The DNS Process (Variable RTT)
&lt;/h4&gt;

&lt;p&gt;An overview of the DNS process for &lt;code&gt;www.google.com&lt;/code&gt; is as follows:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Check browser &amp;amp; OS cache, return if IP found.&lt;/li&gt;
&lt;li&gt;The browser or operating system sends a DNS query to its configured resolver. 

&lt;ol&gt;
&lt;li&gt;DNS resolver checks its cache, return if IP is found.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;DNS resolver sends out a request asking root nameservers.&lt;/li&gt;
&lt;li&gt;A root nameserver responds to the DNS resolver with an IP address to a TLD nameserver (in this case the TLD for extensions of &lt;code&gt;.com&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;DNS resolver sends out another request, now to the TLD nameserver, asking if they know what the IP is.&lt;/li&gt;
&lt;li&gt;TLD nameserver responds back to the DNS resolver with an IP of the authoritative nameserver.&lt;/li&gt;
&lt;li&gt;DNS resolver sends out the final request to the authoritative nameserver asking for the IP.&lt;/li&gt;
&lt;li&gt;The authoritative nameserver will scan zones files to find the domain name:ipaddress mapping and will return whether it exists or not to the DNS resolver.&lt;/li&gt;
&lt;li&gt;Finally, the DNS resolver will now respond back to the browser with the IP of the server the browser is trying to communicate.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhglrqe8nj9us42fuxs8d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhglrqe8nj9us42fuxs8d.png" alt="" width="800" height="450"&gt;&lt;/a&gt;&lt;a href="https://youtu.be/vrxwXXytEuI" title="TITLE" rel="noopener noreferrer"&gt;&lt;/a&gt;&lt;/p&gt;&lt;a href="https://youtu.be/vrxwXXytEuI" title="TITLE" rel="noopener noreferrer"&gt;Visualisation of the DNS process&lt;/a&gt;&lt;p&gt;&lt;/p&gt;

&lt;p&gt;Note that this process is usually incredibly fast and rarely follows through in its entirety because of all the layers of caching. It was designed to be fast!&lt;/p&gt;

&lt;h4&gt;
  
  
  Establishing a connection to the server - TCP Handshake (1 RTT)
&lt;/h4&gt;

&lt;p&gt;Now that the IP address is known, the browser sets up a connection to the server via a &lt;a href="https://www.sciencedirect.com/topics/computer-science/three-way-handshake" rel="noopener noreferrer"&gt;TCP three-way handshake&lt;/a&gt;. This applies to HTTP/1.1 and HTTP/2 connections; HTTP/3 uses a different transport, as we will see below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Transmission_Control_Protocol" rel="noopener noreferrer"&gt;TCP&lt;/a&gt; uses a three-way handshake to establish a reliable connection. The connection is full-duplex, and both sides synchronize (SYN) and acknowledge (ACK) each other. The exchange of these four flags is performed in three steps—SYN, SYN-ACK, and ACK—as shown in&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdn8y466ruwdfllwwtaig.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdn8y466ruwdfllwwtaig.png" alt="" width="355" height="167"&gt;&lt;/a&gt;&lt;a href="https://www.sciencedirect.com/topics/computer-science/three-way-handshake" title="TCP Handskae" rel="noopener noreferrer"&gt;&lt;/a&gt;&lt;/p&gt;&lt;a href="https://www.sciencedirect.com/topics/computer-science/three-way-handshake" title="TCP Handskae" rel="noopener noreferrer"&gt;TCP 3-way handshake&lt;/a&gt;&lt;p&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The client chooses an initial sequence number, set in the first SYN packet. &lt;/li&gt;
&lt;li&gt;The server also chooses its own initial sequence number. &lt;/li&gt;
&lt;li&gt;Each side acknowledges the other's sequence number by incrementing it; this is the acknowledgement number.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Once a connection is established, ACKs typically follow for each segment. The connection will eventually end with an RST (reset or tear down the connection) or FIN (gracefully end the connection).&lt;/p&gt;

&lt;p&gt;This mechanism is designed so that two entities attempting to communicate, in this case, the browser and web server, can negotiate the parameters of the network TCP socket connection before transmitting data, in our case, it will be over HTTPS; the secure version of &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP" rel="noopener noreferrer"&gt;HTTP&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;HTTPS is HTTP with encryption. The only difference between the two protocols is that HTTPS uses &lt;a href="https://en.wikipedia.org/wiki/Transport_Layer_Security" rel="noopener noreferrer"&gt;TLS (SSL)&lt;/a&gt; to encrypt normal HTTP requests and responses. As a result, HTTPS provides a solid layer of security over HTTP. A website that uses HTTP has &lt;code&gt;HTTP://&lt;/code&gt; in its URL, while a website that uses HTTPS has &lt;code&gt;HTTPS://&lt;/code&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Establishing a security protocol - TLS Negotiation (typically 1 RTT with TLS 1.3)
&lt;/h4&gt;

&lt;p&gt;For secure connections established over HTTPS, another "handshake" is required. This handshake, or rather the TLS negotiation, determines which cipher will be used to encrypt the communication, verifies the server, and establishes that a secure connection is in place before beginning the actual transfer of data.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmuxmc254vu339latlf61.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmuxmc254vu339latlf61.png" alt="" width="758" height="340"&gt;&lt;/a&gt;&lt;a href="https://blog.cloudflare.com/keyless-ssl-the-nitty-gritty-technical-details/" title="TSL Hanshake" rel="noopener noreferrer"&gt;&lt;/a&gt;&lt;/p&gt;&lt;a href="https://blog.cloudflare.com/keyless-ssl-the-nitty-gritty-technical-details/" title="TSL Hanshake" rel="noopener noreferrer"&gt;Modern day TLS establishing&lt;/a&gt;&lt;p&gt;&lt;/p&gt;

&lt;p&gt;While making the connection secure adds time to the page load, a secure connection is worth the latency expense, as the data transmitted between the browser and the web server cannot normally be decrypted by a third party. TLS has come a long way: TLS 1.2 typically requires 2 RTT for a full handshake, while TLS 1.3 typically requires just 1. TLS 1.3 also supports 0-RTT early data on some resumed connections, although this has security trade-offs and is not always used.&lt;/p&gt;

&lt;p&gt;For a new HTTP/2 connection using TLS 1.3, we can roughly count 1 RTT for TCP, 1 for TLS, and another for the HTTP request and the start of its response, plus DNS and server processing time. These are simplified figures, not fixed totals; existing connections can skip the handshake entirely.&lt;/p&gt;

&lt;p&gt;It is worth noting that HTTP/3 takes a different approach. It uses &lt;a href="https://www.rfc-editor.org/rfc/rfc9000.html" rel="noopener noreferrer"&gt;QUIC&lt;/a&gt; over UDP instead of TCP, integrating TLS 1.3 into the connection handshake and reducing the round trips needed to establish a secure connection.&lt;/p&gt;

&lt;h3&gt;
  
  
  Fetching
&lt;/h3&gt;

&lt;p&gt;Now that we have a TCP connection setup and the TLS exchange has been completed, the browser can now begin to fetch the page's resources. It starts by fetching the markup document for the page. It does this by using the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP" rel="noopener noreferrer"&gt;HTTP protocol&lt;/a&gt;. In our HTTP/2 example, HTTP requests are sent over TCP and encrypted with Transport Layer Security (TLS); since google uses HTTPS.&lt;/p&gt;

&lt;h4&gt;
  
  
  Browser Caching
&lt;/h4&gt;

&lt;p&gt;Before making a request, however, there is another important optimization worth mentioning: &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/Caching" rel="noopener noreferrer"&gt;HTTP caching&lt;/a&gt;. The browser doesn't necessarily need to download a resource every time it is requested. If it has a reusable response stored in its cache, it may be able to use that instead. This applies to things like HTML documents, CSS, JavaScript, images, and other resources.&lt;/p&gt;

&lt;p&gt;How does the browser know when it can reuse something? The server can provide instructions through HTTP response headers. Take this example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;cache-control: public, max-age=3600
etag: "v1"
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, &lt;code&gt;max-age=3600&lt;/code&gt; tells caches that the response can be considered fresh for 3600 seconds (one hour). The &lt;code&gt;public&lt;/code&gt; directive also allows shared caches to store it. The &lt;code&gt;ETag&lt;/code&gt; is an identifier for a particular version of the response.&lt;/p&gt;

&lt;p&gt;Once the response becomes stale, the browser may need to check with the server again. Instead of downloading the whole resource, it can send a conditional request using an &lt;code&gt;If-None-Match&lt;/code&gt; header with the previously received ETag. If the resource hasn't changed, the server can respond with &lt;code&gt;304 Not Modified&lt;/code&gt;, allowing the browser to reuse the cached body. If it has changed, the server sends an updated response.&lt;/p&gt;

&lt;p&gt;It's also worth distinguishing &lt;code&gt;no-cache&lt;/code&gt;, which requires validation before reuse, from &lt;code&gt;no-store&lt;/code&gt;, which instructs caches not to store the response. And while we won't be going into detail on them here, service workers can also intercept requests, while the back/forward cache can preserve an entire page for history navigation. They are different mechanisms from regular HTTP caching.&lt;/p&gt;

&lt;p&gt;For the rest of our example, let's assume the browser needs to fetch the page from the server.&lt;/p&gt;

&lt;h4&gt;
  
  
  HTTP Request
&lt;/h4&gt;

&lt;p&gt;To fetch a page a &lt;a href="https://www.rfc-editor.org/rfc/rfc9110.html#section-9.2" rel="noopener noreferrer"&gt;safe and idempotent&lt;/a&gt; request is made. We use the HTTP GET request.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;GET&lt;/code&gt;—Requests information from a given server using a &lt;a href="https://en.wikipedia.org/wiki/Uniform_Resource_Identifier" rel="noopener noreferrer"&gt;Uniform Resource Identifier (URI)&lt;/a&gt;. A &lt;a href="https://www.rfc-editor.org/rfc/rfc9110.html#section-9.3.1" rel="noopener noreferrer"&gt;correct implementation&lt;/a&gt; of the GET method is intended to retrieve data, not request changes to the server's state. It is also idempotent, meaning that repeating the same request has the same intended effect as making it once.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There are many other types of HTTP methods:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fegy39l7tc3e4pm965lnq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fegy39l7tc3e4pm965lnq.png" alt="" width="364" height="196"&gt;&lt;/a&gt;&lt;a href="https://datatracker.ietf.org/doc/html/rfc7231#section-8.1.3" title="HTTP method types" rel="noopener noreferrer"&gt;&lt;/a&gt;&lt;/p&gt;&lt;a href="https://datatracker.ietf.org/doc/html/rfc7231#section-8.1.3" title="HTTP method types" rel="noopener noreferrer"&gt;HTTP Methods as per sepecification&lt;/a&gt;&lt;p&gt;&lt;/p&gt;

&lt;p&gt;For fetching our page we are only interested in &lt;code&gt;GET&lt;/code&gt;. A human-readable representation of an HTTP/2 request could look like this (HTTP/2 actually transmits headers in binary frames):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;:method: GET
:scheme: https
:authority: www.google.com
:path: /
user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:89.0) Gecko/20100101 Firefox/89.0
accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
accept-language: en-GB,en;q=0.5
accept-encoding: gzip, deflate, br
upgrade-insecure-requests: 1
cache-control: max-age=0
te: trailers
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  HTTP Response
&lt;/h4&gt;

&lt;p&gt;Once the webserver receives the request. It will parse the request and try to fulfil it. We assume the request is valid and the files are available. It will reply with an HTTP response, attaching the relevant headers and the contents of the requested HTML document to the body of that response structure.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;:status: 200
date: Sun, 18 Jul 2021 00:26:11 GMT
expires: -1
cache-control: private, max-age=0
content-type: text/html; charset=UTF-8
strict-transport-security: max-age=31536000
content-encoding: br
server: gws
content-length: 37418
x-xss-protection: 0
x-frame-options: SAMEORIGIN
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;*the source code of the HTML document will be in the body of the response.&lt;/p&gt;

&lt;h5&gt;
  
  
  HTTP Redirects
&lt;/h5&gt;

&lt;p&gt;Of course, not every HTTP response contains the page we requested. Sometimes the server responds with a &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/Redirections" rel="noopener noreferrer"&gt;redirect&lt;/a&gt;, telling the browser to request another URL instead.&lt;/p&gt;

&lt;p&gt;For example, a response may look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;:status: 302
location: https://www.example.com/new-page
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The browser reads the &lt;code&gt;Location&lt;/code&gt; header and makes another request to that address. Depending on where the new URL points, this might involve another DNS lookup or a new connection to a server.&lt;/p&gt;

&lt;p&gt;Some common redirect status codes are &lt;code&gt;301&lt;/code&gt; and &lt;code&gt;308&lt;/code&gt; (permanent), and &lt;code&gt;302&lt;/code&gt; and &lt;code&gt;307&lt;/code&gt; (temporary). An important distinction is that &lt;code&gt;307&lt;/code&gt; and &lt;code&gt;308&lt;/code&gt; preserve the original request method, while &lt;code&gt;301&lt;/code&gt; and &lt;code&gt;302&lt;/code&gt; may change a &lt;code&gt;POST&lt;/code&gt; into a &lt;code&gt;GET&lt;/code&gt; when followed by a browser.&lt;/p&gt;

&lt;h4&gt;
  
  
  Streaming and Progressive Parsing
&lt;/h4&gt;

&lt;p&gt;So far, we've talked about the HTTP response as if the browser waits for the entire document to arrive before doing anything with it. That isn't quite what happens!&lt;/p&gt;

&lt;p&gt;The response body can arrive in pieces over the network. Once the browser has enough data, it can start processing the HTML while the rest of the document is still downloading. If the response uses compression, such as &lt;code&gt;br&lt;/code&gt; (Brotli), the browser first decompresses the incoming data and decodes it into characters for the HTML parser.&lt;/p&gt;

&lt;p&gt;As those characters become available, the browser can begin tokenizing the HTML and building the DOM tree. Meanwhile, additional parts of the document are still arriving, and the preload scanner may already have discovered other resources such as CSS or JavaScript files.&lt;/p&gt;

&lt;p&gt;This means that by the time the last part of the document arrives, some of the DOM may already be constructed, and the browser may even have displayed part of the page. This isn't always the case, as resources such as stylesheets and blocking scripts can still delay rendering. But it is one of the reasons why browsers can begin displaying a page before everything has finished downloading.&lt;/p&gt;

&lt;h3&gt;
  
  
  Parsing
&lt;/h3&gt;

&lt;p&gt;Once the browser receives the response, it can begin parsing the information received. Parsing is the step the browser takes to turn the data it receives over the network into the DOM and CSSOM, which is used by the renderer to paint a page to the screen.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://en.wikipedia.org/wiki/Document_Object_Model" rel="noopener noreferrer"&gt;Document Object Model (DOM)&lt;/a&gt; is an internal representation of the objects that comprise the structure and content of the markup (HTML in this case) document the browser just received. It represents the page so that programs can change the document structure, style, and content. &lt;/p&gt;

&lt;p&gt;The DOM represents the document as nodes and objects. That way, programming languages can connect to the page. There are many different types of nodes in a DOM tree. An example part of the specification for the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Node" rel="noopener noreferrer"&gt;DOM Node Interface&lt;/a&gt; looks as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Node.ELEMENT_NODE&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Node.ATTRIBUTE_NODE&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Node.TEXT_NODE&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Node.CDATA_SECTION_NODE&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Node.PROCESSING_INSTRUCTION_NODE&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Node.COMMENT_NODE&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Node.DOCUMENT_NODE&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Node.DOCUMENT_TYPE_NODE&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Node.DOCUMENT_FRAGMENT_NODE&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Node.NOTATION_NODE&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These node types cover all possible nodes in the document. Such representations help programming languages connect to the page so that they can manipulate it.&lt;/p&gt;

&lt;p&gt;To conclude our parsing preface, we need to talk about the CSSOM. &lt;/p&gt;

&lt;p&gt;The &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/CSS_Object_Model" rel="noopener noreferrer"&gt;CSS Object Model (CSSOM)&lt;/a&gt; is a set of APIs allowing the manipulation of CSS from JavaScript. It is much like the DOM, but for the CSS rather than the HTML. It allows users to read and modify CSS style dynamically. It is represented very similarly to the DOM, as a tree, and it will be used along with the DOM to form a render tree so that the browser can begin its rendering process. Let's find out how by going through the entire process.&lt;/p&gt;

&lt;h4&gt;
  
  
  Building the DOM tree
&lt;/h4&gt;

&lt;p&gt;The first step is processing the HTML markup and building the DOM tree. HTML parsing involves tokenization and tree construction. &lt;/p&gt;

&lt;p&gt;HTML may come as a surprise in the world of parsing as it cannot be parsed through conventional means. Unlike XML, modern HTML is not defined by a Document Type Definition (DTD). Instead, the HTML specification defines its own parsing algorithm. I will not be going too much into detail about how this is done but the main reasons for this are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The forgiving nature of the language.&lt;/li&gt;
&lt;li&gt;The fact that browsers have traditional error tolerance to support well-known cases of invalid HTML.&lt;/li&gt;
&lt;li&gt;The parsing process is reentrant. For other languages, the source doesn't change during parsing, but in HTML, dynamic code (such as script elements containing &lt;code&gt;document.write()&lt;/code&gt; calls) can add extra tokens, so the parsing process actually modifies the input.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Unable to use the regular parsing techniques, browsers implement the HTML parsing algorithm defined by the specification.&lt;/p&gt;

&lt;p&gt;The parsing algorithm is described in detail by the &lt;a href="https://html.spec.whatwg.org/multipage/parsing.html" rel="noopener noreferrer"&gt;HTML Living Standard&lt;/a&gt;. As previously mentioned, the algorithm consists of two stages: tokenization and tree construction.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Tokenization&lt;/strong&gt; is the lexical analysis, parsing the input into tokens. Among HTML tokens are start tags, end tags, attribute names and attribute values.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tree construction&lt;/strong&gt; is essentially creating a tree-based of the parsed tokens and what we will be focusing on—The DOM tree.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The DOM tree describes the content of the document. The &lt;code&gt;&amp;lt;html&amp;gt;&lt;/code&gt; element is the first tag and root node of the document tree. The tree reflects the relationships and hierarchies between different tags. Tags nested within other tags are child nodes. The greater the number of DOM nodes, the longer it takes to construct the DOM tree. Below you can find a visual representation of the DOM tree—The output of the parser:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk2ovvtmkybu182f1ak2b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk2ovvtmkybu182f1ak2b.png" alt="" width="754" height="689"&gt;&lt;/a&gt;&lt;/p&gt;Part of the DOM Tree&lt;p&gt;&lt;/p&gt;

&lt;p&gt;When the parser finds non-blocking resources, such as an image, the browser will request those resources and continue parsing. Parsing can continue when a CSS file is encountered, but &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; tags—particularly those without an async or defer attribute—block rendering, and pause the parsing of HTML. Though the browser's preload scanner hastens this process, excessive scripts can still be a significant bottleneck.&lt;/p&gt;

&lt;h4&gt;
  
  
  Building the CSSOM tree
&lt;/h4&gt;

&lt;p&gt;The second step is processing CSS and building the CSSOM tree. In a similar fashion to the DOM parsing phase, the browser goes through each rule set in the CSS, creating a tree of nodes with parent, child, and sibling relationships based on the CSS selectors.&lt;/p&gt;

&lt;p&gt;In regards to parsing, well, unlike HTML, CSS is a context-free grammar and can be parsed using regular CFG parsing techniques. In fact the &lt;a href="https://www.w3.org/TR/CSS21/grammar.html" rel="noopener noreferrer"&gt;CSS specification defines CSS lexical and syntax grammar&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;As with HTML, the browser needs to convert the received CSS rules into something it can work with. From there, it repeats the HTML-to-object process, but for the CSS.&lt;/p&gt;

&lt;h4&gt;
  
  
  Combining the trees into the render tree
&lt;/h4&gt;

&lt;p&gt;The CSSOM and DOM trees are combined into a render tree, which is then used to compute the layout of each visible element and serves as an input to the paint process that renders the pixels to the screen.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz6lpm4e05fws0naziz4p.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz6lpm4e05fws0naziz4p.png" alt="" width="800" height="374"&gt;&lt;/a&gt;&lt;a href="HERE%20LINK" title="DOM + CSSOM"&gt;&lt;/a&gt;&lt;/p&gt;&lt;a href="HERE%20LINK" title="DOM + CSSOM"&gt;Combining the CSSOM + DOM trees to make the render tree&lt;/a&gt;&lt;p&gt;&lt;/p&gt;

&lt;p&gt;To construct the render tree, the browser roughly does the following:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Starting at the root of the DOM tree, traverse each visible node.

&lt;ul&gt;
&lt;li&gt;Some nodes are not visible (for example, script tags, meta tags, and so on), and are omitted since they are not reflected in the rendered output.&lt;/li&gt;
&lt;li&gt;Some nodes are hidden via CSS and are also omitted from the render tree; for example, the span node—in the example above—is missing from the render tree because we have an explicit rule that sets the "display: none" property on it.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;For each visible node, find the appropriate matching CSSOM rules and apply them.&lt;/li&gt;
&lt;li&gt;Emit visible nodes with content and their computed styles. &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The final output is a render that contains both the content and style information of all the visible content on the screen. With the render tree in place, we can proceed to the "layout" stage.&lt;/p&gt;

&lt;h4&gt;
  
  
  Preload Scanner
&lt;/h4&gt;

&lt;p&gt;While the browser's main thread is busing building the DOM tree it has a helper worker scan through the content available. This helper is the &lt;a href="https://ariya.io/2013/04/css-preload-scanner-in-webkit" rel="noopener noreferrer"&gt;preload scanner&lt;/a&gt; and will prepare high priority fetch request for resources like CSS, JavaScript, and web fonts. This is an optimization added over the parsing stage as it would take far too long to make these requests as the parser finds references to them.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"stylesheet"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"styles.css"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"myscript.js"&lt;/span&gt; &lt;span class="na"&gt;async&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"myimage.jpg"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"image description"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"anotherscript.js"&lt;/span&gt; &lt;span class="na"&gt;async&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Taking the example above, the preload scanner will try to find the scripts and images, and start downloading them. The &lt;code&gt;async&lt;/code&gt; and &lt;code&gt;defer&lt;/code&gt; attributes affect when scripts execute:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;async&lt;/code&gt;: When present, it specifies that the script will be executed asynchronously as soon as it is available.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;defer&lt;/code&gt;: When present, it specifies that the script is executed when the page has finished parsing, before the &lt;code&gt;DOMContentLoaded&lt;/code&gt; event.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Another important part of this optimization is &lt;strong&gt;fetch priority&lt;/strong&gt;. Not all resources are equally important! The browser assigns priorities to requests so that resources needed early, such as render-blocking stylesheets, can be fetched ahead of less important ones.&lt;/p&gt;

&lt;p&gt;We can also provide a hint using the &lt;a href="https://web.dev/articles/fetch-priority" rel="noopener noreferrer"&gt;&lt;code&gt;fetchpriority&lt;/code&gt; attribute&lt;/a&gt;. For example, &lt;code&gt;&amp;lt;img src="hero.jpg" fetchpriority="high" alt="..."&amp;gt;&lt;/code&gt; tells the browser that this image is particularly important. It is only a hint though; the browser still makes the final decision. Unlike &lt;code&gt;async&lt;/code&gt; and &lt;code&gt;defer&lt;/code&gt;, this attribute affects fetching priority, not when a script executes.&lt;/p&gt;

&lt;p&gt;Waiting to obtain CSS doesn't block HTML parsing or downloading, but it does block JavaScript because JavaScript is often used to query CSS properties’ impact on elements.&lt;/p&gt;

&lt;h4&gt;
  
  
  JavaScript Compilation
&lt;/h4&gt;

&lt;p&gt;While the CSS is being parsed and the CSSOM created, other assets, including JavaScript files, are downloading (thanks to the preload scanner). JavaScript is interpreted, compiled, parsed and executed. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0pdfl3y8t9d7vm2qaxlg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0pdfl3y8t9d7vm2qaxlg.png" alt="" width="800" height="356"&gt;&lt;/a&gt;&lt;a href="https://v8.dev/blog/background-compilation" title="TITLE" rel="noopener noreferrer"&gt;&lt;/a&gt;&lt;/p&gt;&lt;a href="https://v8.dev/blog/background-compilation" title="TITLE" rel="noopener noreferrer"&gt;Overview of the JS compilation process&lt;/a&gt;&lt;p&gt;&lt;/p&gt;

&lt;p&gt;The scripts are parsed into &lt;a href="https://en.wikipedia.org/wiki/Abstract_syntax_tree" rel="noopener noreferrer"&gt;abstract syntax trees&lt;/a&gt;. Like in the above diagram (from V8's engine blog), some browser engines take the Abstract Syntax Tree and pass it into an interpreter, outputting bytecode which is executed on the main thread. This is known as JavaScript compilation.&lt;/p&gt;

&lt;h4&gt;
  
  
  Building the Accessibility Tree
&lt;/h4&gt;

&lt;p&gt;The browser also builds an accessibility tree that assistive devices use to parse and interpret content. The &lt;a href="https://wicg.github.io/aom/explainer.html" rel="noopener noreferrer"&gt;accessibility object model (AOM)&lt;/a&gt; is like a semantic version of the DOM. The browser updates the accessibility tree when the DOM is updated. The accessibility tree is not modifiable by assistive technologies themselves.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa4e181v8hq7vmuvdegh5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa4e181v8hq7vmuvdegh5.png" alt="" width="735" height="401"&gt;&lt;/a&gt;&lt;/p&gt;Build and use process of the AOM&lt;p&gt;&lt;/p&gt;

&lt;p&gt;Until the AOM is built, the content is not accessible to screen readers.&lt;/p&gt;

&lt;h3&gt;
  
  
  Rendering
&lt;/h3&gt;

&lt;p&gt;Now that the information has been parsed the browser can begin to display it. To achieve this the browser will now use the render tree to produce a visual representation of the document. Rendering steps include layout, paint and, in some cases, compositing.&lt;/p&gt;

&lt;h4&gt;
  
  
  Critical Rendering Path
&lt;/h4&gt;

&lt;p&gt;Now is a good time to introduce the notion of the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/Performance/Critical_rendering_path" rel="noopener noreferrer"&gt;Critical Rendering Path&lt;/a&gt;. The best way to visualise it is with a diagram:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F081c6qn9jf63g3038yt5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F081c6qn9jf63g3038yt5.png" alt="" width="800" height="231"&gt;&lt;/a&gt;&lt;a href="https://guillermo.at/browser-critical-render-path" title="CRP" rel="noopener noreferrer"&gt;&lt;/a&gt;&lt;/p&gt;&lt;a href="https://guillermo.at/browser-critical-render-path" title="CRP" rel="noopener noreferrer"&gt;The Critical Rendering Path&lt;/a&gt;&lt;p&gt;&lt;/p&gt;

&lt;p&gt;Optimizing the critical rendering path improves the time to first render. It is important to ensure reflows and repaints can happen at the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Frame_Timing_API" rel="noopener noreferrer"&gt;goal of 60 frames per second&lt;/a&gt; (for performant user interactions).&lt;/p&gt;

&lt;p&gt;We won't be going into detail on how to optimise the CRP but the general gist relies on improving page load speed by prioritizing which resources get loaded, controlling the order in which they are loaded, and reducing the file sizes of those resources.&lt;/p&gt;

&lt;p&gt;Now let's move on to the rendering stages.&lt;/p&gt;

&lt;h4&gt;
  
  
  Layout
&lt;/h4&gt;

&lt;p&gt;Layout is the first rendering stage, where the geometry and positioning of the render tree nodes are determined. Once the render tree is built, the layout commences. &lt;/p&gt;

&lt;p&gt;Layout is a recursive process. It begins at the root renderer, which corresponds to the &lt;code&gt;&amp;lt;html&amp;gt;&lt;/code&gt; element of the HTML document. Layout continues recursively through some or all of the frame hierarchy, computing geometric information for each renderer that requires it. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5t8ph12snekwblpjyf89.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5t8ph12snekwblpjyf89.png" alt="" width="800" height="496"&gt;&lt;/a&gt;&lt;/p&gt;Layout stage&lt;p&gt;&lt;/p&gt;

&lt;p&gt;At the end of the layout stage, a tree similar to the one above is generated with what we call blocks/Coxes as nodes. Blocks/Boxes hold the geometric information of DOM objects and nodes.&lt;/p&gt;

&lt;h5&gt;
  
  
  Dirty bit system
&lt;/h5&gt;

&lt;p&gt;In order not to do a full layout for every small change, browsers use a "dirty bit" system. A renderer that is changed or added marks itself and its children as "dirty": needing layout.&lt;/p&gt;

&lt;p&gt;There are two flags: &lt;br&gt;
    - &lt;strong&gt;dirty:&lt;/strong&gt; node needs a layout.&lt;br&gt;
    - &lt;strong&gt;children are dirty:&lt;/strong&gt; node has at least one child that needs a layout.&lt;/p&gt;

&lt;h5&gt;
  
  
  Layout Algorithm
&lt;/h5&gt;

&lt;p&gt;Using the dirty bit system browsers can now perform an algorithm to generate the layout. A high-level abstraction of that algorithm is as folows:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Parent node determines its own width.&lt;/li&gt;
&lt;li&gt;Parent goes over children and:

&lt;ol&gt;
&lt;li&gt;Calculate child render's size&lt;/li&gt;
&lt;li&gt;Calls child layout if they have a dirty descendant&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;Parent uses children's accumulative heights and the heights of margins and padding to set its own height–this will be used by the parent renderer's parent.&lt;/li&gt;
&lt;li&gt;Sets its dirty bit to false.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;An added important concept is that of &lt;strong&gt;reflow&lt;/strong&gt;. As previously mentioned, the first time the size and position of nodes are determined is called &lt;strong&gt;layout&lt;/strong&gt;. Subsequent recalculations of node size and locations are called &lt;strong&gt;reflows&lt;/strong&gt;. As an example, suppose the initial layout occurs before the image is returned. Since we didn't declare the size of our image, there will be a reflow once the image size is known!&lt;/p&gt;

&lt;h4&gt;
  
  
  Paint
&lt;/h4&gt;

&lt;p&gt;The third and last stage of rendering. In this painting phase, the browser converts each box calculated in the layout phase to actual pixels on the screen. Painting involves drawing every visual part of an element to the screen, including text, colours, borders, shadows, and replaced elements like buttons and images. The browser needs to do this super quickly.&lt;/p&gt;

&lt;h5&gt;
  
  
  Painting order
&lt;/h5&gt;

&lt;p&gt;&lt;a href="https://www.w3.org/TR/CSS21/zindex.html" rel="noopener noreferrer"&gt;CSS2 defines the order of the painting process&lt;/a&gt;. This is actually the order in which the elements are stacked in the stacking contexts. This order affects painting since the stacks are painted from back to front. The stacking order of a block renderer is:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;background colour&lt;/li&gt;
&lt;li&gt;background image&lt;/li&gt;
&lt;li&gt;border&lt;/li&gt;
&lt;li&gt;children&lt;/li&gt;
&lt;li&gt;outline&lt;/li&gt;
&lt;/ol&gt;

&lt;h5&gt;
  
  
  Paint Layers
&lt;/h5&gt;

&lt;p&gt;Painting can break the elements in the layout tree into layers. Promoting content into layers on the GPU (instead of the main thread on the CPU) improves paint and repaint performance. There are specific properties and elements that instantiate a layer, including &lt;code&gt;&amp;lt;video&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;canvas&amp;gt;&lt;/code&gt;, and any element which has the CSS properties of opacity, a 3D transform, will-change, and a few others. These nodes will be painted onto their own layer, along with their descendants, unless a descendant necessitates its own layer for one (or more) of the above reasons.&lt;/p&gt;

&lt;p&gt;Layers do improve performance but are expensive when it comes to memory management, so should not be overused as part of web performance optimization strategies.&lt;/p&gt;

&lt;h4&gt;
  
  
  Compositing
&lt;/h4&gt;

&lt;p&gt;When sections of the document are drawn in different layers, overlapping each other, compositing is necessary to ensure they are drawn to the screen in the right order and the content is rendered correctly.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr33bwf2r09f27t73az2n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr33bwf2r09f27t73az2n.png" alt="" width="598" height="278"&gt;&lt;/a&gt;&lt;/p&gt;Compositing stage&lt;p&gt;&lt;/p&gt;

&lt;p&gt;As the page continues to load assets, reflows can happen (recall our example image that arrived late).  A reflow sparks a repaint and a re-composite. Had we defined the size of our image, no-reflow would have been necessary, and only the layer that needed to be repainted would be repainted, and composited if necessary. But we didn't include the image size! When the image is obtained from the server, the rendering process goes back to the layout steps and restarts from there.&lt;/p&gt;

&lt;h4&gt;
  
  
  Dynamic Rendering and Updates
&lt;/h4&gt;

&lt;p&gt;By now, we've seen how the browser turns HTML and CSS into pixels on our screen. But rendering isn't something that only happens once! The page can continue changing as JavaScript modifies the DOM, images load, the user resizes their window, or animations update the appearance of elements.&lt;/p&gt;

&lt;p&gt;When something changes, the browser may need to go through parts of the rendering process again. It doesn't necessarily repeat every step. As an overview:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Style recalculation:&lt;/strong&gt; If the styles affecting an element change, the browser may need to calculate its styles again.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Layout:&lt;/strong&gt; Changes affecting size or position can require a new layout (reflow) for the affected elements.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Paint:&lt;/strong&gt; Changes to visual properties, such as a background colour, may need a repaint without requiring a new layout.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Compositing:&lt;/strong&gt; Some changes, such as &lt;code&gt;transform&lt;/code&gt; or &lt;code&gt;opacity&lt;/code&gt;, can often be handled by the compositor without a new layout or paint, provided the element is on a suitable layer.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is why changing an element's width repeatedly can be more expensive than moving it using a transform. It depends on which stages the change causes the browser to repeat.&lt;/p&gt;

&lt;p&gt;For animations, we can use &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Window/requestAnimationFrame" rel="noopener noreferrer"&gt;&lt;code&gt;requestAnimationFrame()&lt;/code&gt;&lt;/a&gt; to request a JavaScript callback before the browser's next repaint. This helps schedule visual updates around the browser's rendering cycle, although lengthy JavaScript work can still block the main thread.&lt;/p&gt;

&lt;p&gt;In general, the browser tries to avoid repeating unnecessary work to keep the page responsive and animations smooth.&lt;/p&gt;

&lt;h3&gt;
  
  
  Finalising
&lt;/h3&gt;

&lt;p&gt;Once the main thread is done painting the page, you would think we would be "all set." That isn't necessarily the case. If the load includes JavaScript, which was correctly deferred and executed after the HTML document has finished parsing, the main thread might still be busy, and not available for scrolling, touch, and other interactions.&lt;/p&gt;

&lt;h4&gt;
  
  
  JavaScript Occupied
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://developer.chrome.com/docs/lighthouse/performance/interactive/" rel="noopener noreferrer"&gt;Time to Interactive (TTI)&lt;/a&gt; was historically used to measure when a page becomes interactive, but was removed from Lighthouse 10 due to its variability. Metrics such as &lt;a href="https://web.dev/articles/tbt" rel="noopener noreferrer"&gt;Total Blocking Time (TBT)&lt;/a&gt; and &lt;a href="https://web.dev/articles/inp" rel="noopener noreferrer"&gt;Interaction to Next Paint (INP)&lt;/a&gt; now provide better insight into different aspects of responsiveness. If the main thread is occupied parsing, compiling, and executing JavaScript, it is not available and therefore not able to respond to user interactions in a timely fashion.&lt;/p&gt;

&lt;p&gt;In our example, maybe the image loaded quickly, but perhaps the anotherscript.js file was 2MB and contained JavaScript that took a long time to execute. In this case, the user could see the page super quickly, but wouldn't be able to scroll without jank while the script occupies the main thread. That is not a good user experience. Avoid occupying the main thread, as demonstrated in this WebPageTest example:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxbkoby5bedm789lskzyb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxbkoby5bedm789lskzyb.png" alt="" width="800" height="466"&gt;&lt;/a&gt;&lt;/p&gt;Example - JavaScript hogging main thread&lt;p&gt;&lt;/p&gt;

&lt;p&gt;In this example, the DOM content load process took over 1.5 seconds, and the main thread was fully occupied that entire time, unresponsive to click events or screen taps.&lt;/p&gt;

&lt;p&gt;One more concept worth mentioning here is the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Execution_model" rel="noopener noreferrer"&gt;JavaScript event loop&lt;/a&gt;. In a browser, JavaScript running on the main thread typically executes one task at a time. These tasks may include running a script, handling a click, or executing a &lt;code&gt;setTimeout()&lt;/code&gt; callback. While a task is running, another main-thread task cannot run, so a long-running script can delay user interactions.&lt;/p&gt;

&lt;p&gt;Once a task finishes, the browser processes queued &lt;strong&gt;microtasks&lt;/strong&gt;, such as callbacks from resolved promises, before moving on to another task. The browser also gets opportunities to render between tasks, but not while the main thread is busy executing a long task. This is one of the reasons why breaking lengthy JavaScript work into smaller tasks can help improve responsiveness.&lt;/p&gt;

&lt;h4&gt;
  
  
  Document Lifecycle Events
&lt;/h4&gt;

&lt;p&gt;Before we conclude, there are a few events and states worth mentioning. The browser exposes these so that JavaScript can tell how far the document has progressed through loading. You may have come across &lt;code&gt;DOMContentLoaded&lt;/code&gt; and &lt;code&gt;load&lt;/code&gt; before, but they don't mean quite the same thing.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;document.readyState&lt;/code&gt;:&lt;/strong&gt; A property that can be &lt;code&gt;loading&lt;/code&gt; while the HTML is being parsed, &lt;code&gt;interactive&lt;/code&gt; once parsing is complete, or &lt;code&gt;complete&lt;/code&gt; once the document and its dependent resources have finished loading.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;DOMContentLoaded&lt;/code&gt;:&lt;/strong&gt; An event that fires after the HTML document has been parsed and deferred scripts (including module scripts) have executed. It does not wait for images and other non-blocking resources to finish loading.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;load&lt;/code&gt;:&lt;/strong&gt; An event that fires when the page and its dependent resources, such as images and stylesheets, have finished loading, excluding resources that are lazy-loaded.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;An important distinction is that these aren't necessarily the moments when the page first becomes visible or responsive. The browser may have already painted content before the &lt;code&gt;load&lt;/code&gt; event, and JavaScript can still occupy the main thread afterwards.&lt;/p&gt;

&lt;h4&gt;
  
  
  The user can now browse the page! 🎉
&lt;/h4&gt;

&lt;p&gt;Yes, after all these stages the user can now both see and interact with the page!&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;For a simple page to be displayed in our browser window it may need to go through:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;DNS Lookup: To find out the IP of the web address.&lt;/li&gt;
&lt;li&gt;TCP Handshake: To set up TCP communication between the client and server for HTTP/1.1 and HTTP/2.&lt;/li&gt;
&lt;li&gt;TLS Handshake: To safeguard the information that will be sent via encryption (integrated into QUIC for HTTP/3).&lt;/li&gt;
&lt;li&gt;Browser Caching: To reuse resources already stored locally when possible.&lt;/li&gt;
&lt;li&gt;HTTP communication: To establish a method of communication that browsers can understand, including redirects and streaming the response.&lt;/li&gt;
&lt;li&gt;Browser Parsing: To parse the HTTP's response—the document of the page to be displayed.&lt;/li&gt;
&lt;li&gt;Browser Rendering: To render the document on the browsers window and update it when something changes.&lt;/li&gt;
&lt;li&gt;Javascript Occupied: To wait for JS to compile and execute as it may hog the main thread.&lt;/li&gt;
&lt;li&gt;Document Lifecycle Events: To signal the progress of document parsing and loading.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It is incredible the number of things that happen for this seemingly simple task to be accomplished. Truly an impressive journey for our little page :)&lt;/p&gt;

&lt;h4&gt;
  
  
  There is more...
&lt;/h4&gt;

&lt;p&gt;In a real-world scenario, our little page may have to tackle even more obstacles before reaching its destination things such as: &lt;a href="https://www.nginx.com/resources/glossary/load-balancing/" rel="noopener noreferrer"&gt;load balancers, proxies&lt;/a&gt;, &lt;a href="https://www.nginx.com/resources/glossary/what-is-a-waf/" rel="noopener noreferrer"&gt;multiple layers of firewalls&lt;/a&gt;, etc... &lt;/p&gt;

&lt;p&gt;These topics are beasts of their own and if you're curious about how they work I recommend looking them up! Perhaps I'll write something for them in the future.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Thank you for reading,&lt;br&gt;
Paulo 😎&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Reference
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/Performance/How_browsers_work#overview" rel="noopener noreferrer"&gt;https://developer.mozilla.org/en-US/docs/Web/Performance/How_browsers_work#overview&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.html5rocks.com/en/tutorials/internals/howbrowserswork" rel="noopener noreferrer"&gt;https://www.html5rocks.com/en/tutorials/internals/howbrowserswork&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developers.google.com/web/fundamentals/" rel="noopener noreferrer"&gt;https://developers.google.com/web/fundamentals/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.cloudflare.com/introducing-0-rtt/" rel="noopener noreferrer"&gt;https://blog.cloudflare.com/introducing-0-rtt/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.cloudflare.com/keyless-ssl-the-nitty-gritty-technical-details/" rel="noopener noreferrer"&gt;https://blog.cloudflare.com/keyless-ssl-the-nitty-gritty-technical-details/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://community.fs.com/blog/tcpip-vs-osi-whats-the-difference-between-the-two-models.html" rel="noopener noreferrer"&gt;https://community.fs.com/blog/tcpip-vs-osi-whats-the-difference-between-the-two-models.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.sciencedirect.com/topics/computer-science/three-way-handshake" rel="noopener noreferrer"&gt;https://www.sciencedirect.com/topics/computer-science/three-way-handshake&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://v8.dev/blog/background-compilation" rel="noopener noreferrer"&gt;https://v8.dev/blog/background-compilation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.smashingmagazine.com/2016/12/gpu-animation-doing-it-right/" rel="noopener noreferrer"&gt;https://www.smashingmagazine.com/2016/12/gpu-animation-doing-it-right/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.rfc-editor.org/rfc/rfc9110.html" rel="noopener noreferrer"&gt;https://www.rfc-editor.org/rfc/rfc9110.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.rfc-editor.org/rfc/rfc9113.html" rel="noopener noreferrer"&gt;https://www.rfc-editor.org/rfc/rfc9113.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.rfc-editor.org/rfc/rfc8446.html" rel="noopener noreferrer"&gt;https://www.rfc-editor.org/rfc/rfc8446.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.rfc-editor.org/rfc/rfc9000.html" rel="noopener noreferrer"&gt;https://www.rfc-editor.org/rfc/rfc9000.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.rfc-editor.org/rfc/rfc9114.html" rel="noopener noreferrer"&gt;https://www.rfc-editor.org/rfc/rfc9114.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.chrome.com/docs/chromium/renderingng-architecture" rel="noopener noreferrer"&gt;https://developer.chrome.com/docs/chromium/renderingng-architecture&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.chrome.com/docs/lighthouse/performance/interactive" rel="noopener noreferrer"&gt;https://developer.chrome.com/docs/lighthouse/performance/interactive&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/script" rel="noopener noreferrer"&gt;https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/script&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/Caching" rel="noopener noreferrer"&gt;https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/Caching&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/Redirections" rel="noopener noreferrer"&gt;https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/Redirections&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/Performance/Guides/How_browsers_work" rel="noopener noreferrer"&gt;https://developer.mozilla.org/en-US/docs/Web/Performance/Guides/How_browsers_work&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://web.dev/articles/fetch-priority" rel="noopener noreferrer"&gt;https://web.dev/articles/fetch-priority&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/Performance/Guides/Animation_performance_and_frame_rate" rel="noopener noreferrer"&gt;https://developer.mozilla.org/en-US/docs/Web/Performance/Guides/Animation_performance_and_frame_rate&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Window/requestAnimationFrame" rel="noopener noreferrer"&gt;https://developer.mozilla.org/en-US/docs/Web/API/Window/requestAnimationFrame&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Execution_model" rel="noopener noreferrer"&gt;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Execution_model&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Document/readyState" rel="noopener noreferrer"&gt;https://developer.mozilla.org/en-US/docs/Web/API/Document/readyState&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Document/DOMContentLoaded_event" rel="noopener noreferrer"&gt;https://developer.mozilla.org/en-US/docs/Web/API/Document/DOMContentLoaded_event&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Window/load_event" rel="noopener noreferrer"&gt;https://developer.mozilla.org/en-US/docs/Web/API/Window/load_event&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>architecture</category>
      <category>html</category>
      <category>css</category>
      <category>javascript</category>
    </item>
  </channel>
</rss>
