<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ webworker - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Browse thousands of programming tutorials written by experts. Learn Web Development, Data Science, DevOps, Security, and get developer career advice. ]]>
        </description>
        <link>https://www.freecodecamp.org/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ webworker - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Wed, 24 Jun 2026 20:19:14 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/tag/webworker/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ How Web Workers Work in JavaScript – With a Practical JS Example ]]>
                </title>
                <description>
                    <![CDATA[ In this article, I will walk you through an example that will show you how web workers function in JavaScript with the help of WebSockets.  I think it's helpful to work with a practical use case because it is much simpler to understand the concepts w... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-webworkers-work-in-javascript-with-example/</link>
                <guid isPermaLink="false">66bb5543f55324ca867c88d4</guid>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ websocket ]]>
                    </category>
                
                    <category>
                        <![CDATA[ webworker ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Keyur Paralkar ]]>
                </dc:creator>
                <pubDate>Tue, 04 Jan 2022 00:31:54 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2022/01/christopher-burns-8KfCR12oeUM-unsplash-1.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In this article, I will walk you through an example that will show you how web workers function in JavaScript with the help of WebSockets. </p>
<p>I think it's helpful to work with a practical use case because it is much simpler to understand the concepts when you can relate them to real life. </p>
<p>So in this guide, you will be learning what web workers are in JavaScript, you'll get a brief introduction to WebSockets, and you'll see how you can manage sockets in the proper way. </p>
<p>This article is quite application/hands-on oriented, so I would suggest trying the example out as you go along to get a much better understanding.</p>
<p>Let’s dive in.</p>
<h2 id="heading-table-of-contents">Table of contents</h2>
<ul>
<li><a class="post-section-overview" href="#heading-prerequisites">Prerequisites</a></li>
<li><a class="post-section-overview" href="#heading-what-are-web-workers-in-javascript">What are web workers in JavaScript?</a></li>
<li><a class="post-section-overview" href="#heading-brief-introduction-to-web-sockets">Brief introduction to web sockets</a></li>
<li><a class="post-section-overview" href="#heading-use-case-description">Use case description</a></li>
<li><a class="post-section-overview" href="#heading-project-structure">Project structure</a></li>
<li><a class="post-section-overview" href="#heading-client-and-server-application">Client and Server architecture</a></li>
<li><a class="post-section-overview" href="#heading-worker-system">Worker System</a></li>
<li><a class="post-section-overview" href="#heading-communication-between-the-ui-and-the-socket-via-web-worker">Communication between the UI and the socket via web worker</a></li>
<li><a class="post-section-overview" href="#heading-summary">Summary</a></li>
</ul>
<h2 id="heading-prerequisites">Prerequisites</h2>
<p>Before you start reading this article, you should have a basic understanding of the following topics:</p>
<ul>
<li>Class Diagrams: We are going to use them to showcase our example. Here are a couple resources you can use to learn more about them: <ul>
<li><a target="_blank" href="https://drawio-app.com/uml-class-diagrams-in-draw-io/">Class diagrams</a></li>
<li><a target="_blank" href="https://www.freecodecamp.org/news/uml-diagrams-full-course/">UML Diagram course</a></li>
</ul>
</li>
<li><a target="_blank" href="https://www.notion.so/JS-Classes-a-boon-to-the-society-6360d1a702fe49da9b7ba98b0e03fe37">Context Diagram and Container Diagrams</a></li>
<li><a target="_blank" href="https://reactjs.org/">React</a></li>
<li>Web sockets<ul>
<li><a target="_blank" href="https://javascript.info/websocket">Introduction to sockets</a></li>
<li><a target="_blank" href="https://blog.sessionstack.com/how-javascript-works-deep-dive-into-websockets-and-http-2-with-sse-how-to-pick-the-right-path-584e6b8e3bf7">How JavaScript works: Deep dive into WebSockets and HTTP/2 with SSE + how to pick the right path</a></li>
</ul>
</li>
<li><a target="_blank" href="https://blog.kevinchisholm.com/javascript/difference-between-scope-and-context/">Difference between scope and context</a></li>
<li><a target="_blank" href="https://developer.mozilla.org/en-US/docs/Glossary/Global_object">Global objects</a></li>
</ul>
<h2 id="heading-what-are-web-workers-in-javascript">What are web workers in JavaScript?</h2>
<p>A web worker is a piece of browser functionality. It is the real OS threads that can be spawned in the background of your current page so that it can perform complex and resource-intensive tasks. </p>
<p>Imagine that you have some large data to fetch from the server, or some complex rendering needs to be done on the UI. If you do this directly on your webpage then the page might get jankier and will impact the UI. </p>
<p>To mitigate this, you can simply create a thread – that is a web worker – and let the web worker take care of the complex stuff.  </p>
<p>You can communicate with the web worker in a pretty simple manner which can be used to transfer data to and fro from the worker to the UI.</p>
<p>Common examples of web workers would be: </p>
<ul>
<li>Dashboard pages that display real-time data such as stock prices, real-time active users, and so on</li>
<li>Fetching huge files from the server</li>
<li>Autosave functionality</li>
</ul>
<p>You can create a web worker using the following syntax:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> worker = <span class="hljs-keyword">new</span> Worker(<span class="hljs-string">"&lt;worker_file&gt;.js"</span>);
</code></pre>
<p><code>Worker</code> is an API interface that lets you create a thread in the background. We need to pass a parameter, that is a <code>&lt;worker_file&gt;.js</code> file. This specifies the worker file the API needs to execute.</p>
<p><strong>NOTE</strong>: A thread is created once a <code>Worker</code> call is initiated. This thread only communicates with its creator, that is the file which created this thread.</p>
<p>A worker can be shared or used by multiple consumers/scripts. These are called shared workers. The syntax of the shared worker is very similar to that of the above mentioned workers.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> worker = <span class="hljs-keyword">new</span> SharedWorker(<span class="hljs-string">"&lt;worker_file&gt;.js"</span>);
</code></pre>
<p>You can read more about <code>SharedWorker</code>s in <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/API/SharedWorker">this guide</a>.</p>
<h3 id="heading-history-of-web-workers">History of web workers</h3>
<p>Web workers execute in a different context, that is they do not execute in a global scope such as window context. Web workers have their own dedicated worker context which is called <code>DedicatedWorkerGlobalScope</code>.</p>
<p>There are some cases where you can't use web workers, though. For example, you can't use them to manipulate the DOM or the properties of the window object. This is because the worker does not have the access to the window object. </p>
<p>Web workers can also spawn new web workers. Web workers communicate with their creator using certain methods like <code>postMessage</code>, <code>onmessage</code>, and <code>onerror</code>. We will look into these methods closely in the later sections of this article.</p>
<h2 id="heading-brief-introduction-to-web-sockets">Brief Introduction to Web Sockets</h2>
<p>A web socket is a type of communication that happens between two parties/entities using a WebSocket protocol. It actually provides a way to communicate between the two connected entities in a persistent manner. </p>
<p>You can create a simple web socket like below:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> socket = <span class="hljs-keyword">new</span> WebSocket(<span class="hljs-string">"ws://example.com"</span>);
</code></pre>
<p>Over here we have created a simple socket connection. You'll notice that we have passed a parameter to the <code>WebSocket</code> constructor. This parameter is a URL at which the connection should be established. </p>
<p>You can read more about web sockets by referring to the <strong>Websockets</strong> link in the prerequisites.</p>
<h2 id="heading-use-case-description">Use Case Description</h2>
<p><strong>NOTE:</strong> Context, Container, and Class diagrams drawn in this blog post don't accurately follow the exact conventions of these diagrams. They're approximated here so that you can understand the basic concepts.</p>
<p>Before we start, I would suggest reading up on c4models, container diagrams, and context diagrams. You can find resources about them in the prerequisites section.</p>
<p>In this article, we are going to consider the following use case: data transfer using web workers via socket protocol.</p>
<p>We are going to build a web application which will plot the data on a line chart every 1.5 seconds. The web application will receive the data from the socket connection via web workers. Below is the context diagram of our use case:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/01/c4_webworker.drawio--2-.png" alt="Image" width="600" height="400" loading="lazy">
<em>Container Diagram</em></p>
<p>As you can see from the above diagram, there are 4 main components to our use case:</p>
<ol>
<li>Person: A user who is going to use our application</li>
<li>Software system: Client App – This is the UI of our application. It consists of DOM elements and a web worker.</li>
<li>Software system: Worker system – This is a worker file that resides in the client app. It is responsible for creating a worker thread and establishing the socket connection.</li>
<li>Software system: Server application – This is a simple JavaScript file which can be executed by <code>node</code> to create a socket server. It consists of code which helps to read messages from the socket connection.</li>
</ol>
<p>Now that we understand the use case, let's dive deep into each of these modules and see how the whole application works.</p>
<h2 id="heading-project-structure"><strong>Project</strong> Structure</h2>
<p>Please follow this <a target="_blank" href="https://github.com/keyurparalkar/webworker_examples">link</a> to get the full code for the project that I developed for this article.</p>
<p>Our project is divided into two folders. First is the server folder which consists of server code. The second is the client folder, which consists of the client UI, that is a React application and the web worker code. </p>
<p>Following is the directory structure:</p>
<pre><code>├── client
│   ├── package.json
│   ├── package-lock.json
│   ├── public
│   │   ├── favicon.ico
│   │   ├── index.html
│   │   ├── logo192.png
│   │   ├── logo512.png
│   │   ├── manifest.json
│   │   └── robots.txt
│   ├── README.md
│   ├── src
│   │   ├── App.css
│   │   ├── App.jsx
│   │   ├── components
│   │   │   ├── LineChartSocket.jsx
│   │   │   └── Logger.jsx
│   │   ├── index.css
│   │   ├── index.js
│   │   ├── pages
│   │   │   └── Homepage.jsx
│   │   ├── wdyr.js
│   │   └── workers
│   │       └── main.worker.js
│   └── yarn.lock
└── server
    ├── package.json
    ├── package-lock.json
    └── server.mjs
</code></pre><p>To run the application, you first need to start the socket server. Execute the following commands one at a time to start the socket server (assuming you are in the parent directory):</p>
<pre><code class="lang-shell">cd server
node server.mjs
</code></pre>
<p>Then start the client app by running the following commands (assuming you are in the parent directory):</p>
<pre><code class="lang-shell">cd client
yarn run start
</code></pre>
<p>Open <code>http://localhost:3000</code> to start the web app.</p>
<h2 id="heading-client-and-server-application">Client and Server Application</h2>
<p>The client application is a simple React application, that is <a target="_blank" href="https://create-react-app.dev/">CRA app</a>, which consists of a Homepage. This home page consists of the following elements:</p>
<ul>
<li>Two buttons: <code>start connection</code> and <code>stop connection</code> which will help to start and stop the socket connection as required.</li>
<li>A line chart component - This component will plot the data that we receive from the socket at regular intervals.</li>
<li>Logged message - This is a simple React component that will display the connection status of our web sockets.</li>
</ul>
<p>Below is the container diagram of our client application.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/01/Untitled.png" alt="Image" width="600" height="400" loading="lazy">
<em>Container Diagram: Client Application</em></p>
<p>Below is how the UI will look:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/01/Screenshot-from-2021-12-28-08-32-06.png" alt="Image" width="600" height="400" loading="lazy">
<em>Actual UI</em></p>
<p>To check out the code for the client UI, go to the client folder. This is a regular create-react-app, except that I have removed some boilerplate code that we don't need for this project. </p>
<p><code>App.jsx</code> is actually the starter code. If you check this out, we have called the <code>&lt;Homepage /&gt;</code> component in it.</p>
<p>Now let's have a look at the <code>Homepage</code> component.</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> Homepage = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> [worker, setWorker] = useState(<span class="hljs-literal">null</span>);
  <span class="hljs-keyword">const</span> [res, setRes] = useState([]);
  <span class="hljs-keyword">const</span> [log, setLog] = useState([]);
  <span class="hljs-keyword">const</span> [buttonState, setButtonState] = useState(<span class="hljs-literal">false</span>);

  <span class="hljs-keyword">const</span> hanldeStartConnection = <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-comment">// Send the message to the worker [postMessage]</span>
    worker.postMessage({
      <span class="hljs-attr">connectionStatus</span>: <span class="hljs-string">"init"</span>,
    });
  };

  <span class="hljs-keyword">const</span> handleStopConnection = <span class="hljs-function">() =&gt;</span> {
    worker.postMessage({
      <span class="hljs-attr">connectionStatus</span>: <span class="hljs-string">"stop"</span>,
    });
  };

    <span class="hljs-comment">//UseEffect1</span>
  useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> myWorker = <span class="hljs-keyword">new</span> Worker(
      <span class="hljs-keyword">new</span> URL(<span class="hljs-string">"../workers/main.worker.js"</span>, <span class="hljs-keyword">import</span>.meta.url)
    ); <span class="hljs-comment">//NEW SYNTAX</span>
    setWorker(myWorker);

    <span class="hljs-keyword">return</span> <span class="hljs-function">() =&gt;</span> {
      myWorker.terminate();
    };
  }, []);

    <span class="hljs-comment">//UseEffect2</span>
  useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">if</span> (worker) {
      worker.onmessage = <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">e</span>) </span>{
        <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> e.data === <span class="hljs-string">"string"</span>) {
          <span class="hljs-keyword">if</span>(e.data.includes(<span class="hljs-string">"["</span>)){
            setLog(<span class="hljs-function">(<span class="hljs-params">preLogs</span>) =&gt;</span> [...preLogs, e.data]);
          } <span class="hljs-keyword">else</span> {
            setRes(<span class="hljs-function">(<span class="hljs-params">prevRes</span>) =&gt;</span> [...prevRes, { <span class="hljs-attr">stockPrice</span>: e.data }]);
          }
        }

        <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> e.data === <span class="hljs-string">"object"</span>) {
          setButtonState(e.data.disableStartButton);
        }
      };
    }
  }, [worker]);

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"stats"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"control-panel"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">h3</span>&gt;</span>WebWorker Websocket example<span class="hljs-tag">&lt;/<span class="hljs-name">h3</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">button</span>
            <span class="hljs-attr">id</span>=<span class="hljs-string">"start-connection"</span>
            <span class="hljs-attr">onClick</span>=<span class="hljs-string">{hanldeStartConnection}</span>
            <span class="hljs-attr">disabled</span>=<span class="hljs-string">{!worker</span> || <span class="hljs-attr">buttonState</span>}
          &gt;</span>
            Start Connection
          <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
          <span class="hljs-symbol">&amp;nbsp;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">button</span>
            <span class="hljs-attr">id</span>=<span class="hljs-string">"stop-connection"</span>
            <span class="hljs-attr">onClick</span>=<span class="hljs-string">{handleStopConnection}</span>
            <span class="hljs-attr">disabled</span>=<span class="hljs-string">{!buttonState}</span>
          &gt;</span>
            Stop Connection
          <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">LineChartComponent</span> <span class="hljs-attr">data</span>=<span class="hljs-string">{res}</span> /&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Logger</span> <span class="hljs-attr">logs</span>=<span class="hljs-string">{log}/</span>&gt;</span>
    <span class="hljs-tag">&lt;/&gt;</span></span>
  );
};
</code></pre>
<p>As you can see, it's just a regular functional component that renders two buttons – a line chart, and a custom component <code>Logger</code>. </p>
<p>Now that we know how our homepage component looks, let's dive into how the web worker thread is actually created. In the above component you can see there are two <code>useEffect</code> hooks used. </p>
<p>The first one is used for creating a new worker thread. It's a simple call to the <code>Worker</code> constructor with a new operator as we have seen in the previous section of this article. </p>
<p>But there are some difference over here: we have passed an URL object to the worker constructor rather than passing the path of the worker file in the string.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> myWorker = <span class="hljs-keyword">new</span> Worker(<span class="hljs-keyword">new</span> URL(<span class="hljs-string">"../workers/main.worker.js"</span>, <span class="hljs-keyword">import</span>.meta.url));
</code></pre>
<p>You can read more about this syntax <a target="_blank" href="https://webpack.js.org/guides/web-workers/">here</a>.</p>
<p>If you try to import this web worker like below, then our create-react-app won’t be able to load/bundle it properly so you will get an error since it has not found the worker file during bundling:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> myWorker = <span class="hljs-keyword">new</span> Worker(<span class="hljs-string">"../workers/main.worker.js"</span>);
</code></pre>
<p>Next, we also don’t want our application to run the worker thread even after the refresh, or don’t want to spawn multiple threads when we refresh the page. To mitigate this, we'll return a callback in the same useEffect. We use this callback to perform cleanups when the component unmounts. In this case, we are terminating the worker thread.</p>
<p>We use the <code>useEffect2</code> to handle the messages received from the worker.</p>
<p>Web workers have a build-in property called <code>onmessage</code> which helps receive any messages sent by the worker thread. The <code>onmessage</code> is an event handler of the worker interface. It gets triggered whenever a  message event is triggered. This message event is generally triggered whenever the <code>postMessage</code> handler is executed (we will look more into this in a later section).</p>
<p>So in order for us to send a message to the worker thread, we have created two handlers. The first is <code>handleStartConnection</code> and the second is <code>handleStopConnection</code>. Both of them use the <code>postMessage</code> method of the worker interface to send the message to the worker thread. </p>
<p>We will talk about the message <code>{connectionStatus: init}</code> in our next section.</p>
<p>You can read more about the internal workings of the <code>onmessage</code> and <code>postMessage</code> in the following resources:</p>
<ul>
<li><a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/API/Worker/onmessage">Onmessage</a></li>
<li><a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/API/DedicatedWorkerGlobalScope/postMessage">Postmessage</a></li>
</ul>
<p>Since we now have a basic understanding about how our client code is working, then let's move on to learn about the <strong>Worker System in our context diagram above.</strong></p>
<h2 id="heading-worker-system">Worker System</h2>
<p>To understand the code in this section, make sure you go through the file <code>src/workers/main.worker.js</code>.</p>
<p>To help you understand what's going on here, we will divide this code into three parts:</p>
<ol>
<li>A <code>self.onmessage</code> section</li>
<li>How the socket connection is managed using the <code>socketManagement()</code> function</li>
<li>Why we need the <code>socketInstance</code> variable at the top</li>
</ol>
<h3 id="heading-how-selfonmessage-works">How <code>self.onmessage</code> works</h3>
<p>Whenever you create a web worker application, you generally write a worker file which handles all the complex scenarios that you want the worker to perform. This all happens in the <code>main.worker.js</code> file. This file is our worker file. </p>
<p>In the above section, we saw that we established a new worker thread in the <code>useEffect</code>. Once we created the thread, we also attached the two handlers to the respective <code>start</code> and <code>stop</code> connection buttons. </p>
<p>The <code>start connection</code> button will execute the <code>postMessage</code> method with message: <code>{connectionStatus: init}</code> . This triggers the message event, and since the message event is triggered, all the message events are captured by the <code>onmessage</code> property. </p>
<p>In our <code>main.worker.js</code> file, we have attached a handler to this <code>onmessage</code> property:</p>
<pre><code class="lang-javascript">self.onmessage = <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">e</span>) </span>{
  <span class="hljs-keyword">const</span> workerData = e.data;
  postMessage(<span class="hljs-string">"[WORKER] Web worker onmessage established"</span>);
  <span class="hljs-keyword">switch</span> (workerData.connectionStatus) {
    <span class="hljs-keyword">case</span> <span class="hljs-string">"init"</span>:
      socketInstance = createSocketInstance();
      socketManagement();
      <span class="hljs-keyword">break</span>;

    <span class="hljs-keyword">case</span> <span class="hljs-string">"stop"</span>:
      socketInstance.close();
      <span class="hljs-keyword">break</span>;

    <span class="hljs-keyword">default</span>:
      socketManagement();
  }
}
</code></pre>
<p>So whenever any message event is triggered in the client, it will get captured in this event handler.  </p>
<p>The message <code>{connectionStatus: init}</code> that we send from the client is received in the event <code>e</code>. Based on the value of connectionStatus we use the switch case to handle the logic. </p>
<p><strong>NOTE:</strong> We have added this switch case because we need to isolate some part of the code which we do not want to execute all the time (we will look into this in a later section).</p>
<h3 id="heading-how-the-socket-connection-is-managed-using-the-socketmanagement-function">How the socket connection is managed using the <code>socketManagement()</code> function</h3>
<p>There are some reasons why I have shifted the logic of creating and managing a socket connection into a separate function. Here is the code for a better understanding of the point I am trying to make:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">socketManagement</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">if</span> (socketInstance) {
    socketInstance.onopen = <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">e</span>) </span>{
      <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"[open] Connection established"</span>);
      postMessage(<span class="hljs-string">"[SOCKET] Connection established"</span>);
      socketInstance.send(<span class="hljs-built_in">JSON</span>.stringify({ <span class="hljs-attr">socketStatus</span>: <span class="hljs-literal">true</span> }));
      postMessage({ <span class="hljs-attr">disableStartButton</span>: <span class="hljs-literal">true</span> });
    };

    socketInstance.onmessage = <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">event</span>) </span>{
      <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`[message] Data received from server: <span class="hljs-subst">${event.data}</span>`</span>);
      postMessage( event.data);
    };

    socketInstance.onclose = <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">event</span>) </span>{
      <span class="hljs-keyword">if</span> (event.wasClean) {
        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`[close] Connection closed cleanly, code=<span class="hljs-subst">${event.code}</span>`</span>);
        postMessage(<span class="hljs-string">`[SOCKET] Connection closed cleanly, code=<span class="hljs-subst">${event.code}</span>`</span>);
      } <span class="hljs-keyword">else</span> {
        <span class="hljs-comment">// e.g. server process killed or network down</span>
        <span class="hljs-comment">// event.code is usually 1006 in this case</span>
        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'[close] Connection died'</span>);
        postMessage(<span class="hljs-string">'[SOCKET] Connection died'</span>);
      }
      postMessage({ <span class="hljs-attr">disableStartButton</span>: <span class="hljs-literal">false</span> });
    };

    socketInstance.onerror = <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">error</span>) </span>{
      <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`[error] <span class="hljs-subst">${error.message}</span>`</span>);
      postMessage(<span class="hljs-string">`[SOCKET] <span class="hljs-subst">${error.message}</span>`</span>);
      socketInstance.close();
    };
  }
}
</code></pre>
<p>This is a function that will help you manage your socket connection:</p>
<ul>
<li>For receiving the message from the socket server we have the <code>onmessage</code> property which is assigned an event handler.</li>
<li>Whenever a socket connection is opened, you can perform certain operations. To do that we have the <code>onopen</code> property which is assigned to an event handler.</li>
<li>And if any error occurs or when we are closing the connection then, we use <code>onerror</code> and <code>onclose</code> properties of the socket.</li>
</ul>
<p>For creating a socket connection there is a separate function altogether:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">createSocketInstance</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">let</span> socket = <span class="hljs-keyword">new</span> WebSocket(<span class="hljs-string">"ws://localhost:8080"</span>);

  <span class="hljs-keyword">return</span> socket;
}
</code></pre>
<p>Now all of these functions are called in a switch case like below in the <code>main.worker.js</code> file:</p>
<pre><code class="lang-javascript">self.onmessage = <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">e</span>) </span>{
  <span class="hljs-keyword">const</span> workerData = e.data;
  postMessage(<span class="hljs-string">"[WORKER] Web worker onmessage established"</span>);
  <span class="hljs-keyword">switch</span> (workerData.connectionStatus) {
    <span class="hljs-keyword">case</span> <span class="hljs-string">"init"</span>:
      socketInstance = createSocketInstance();
      socketManagement();
      <span class="hljs-keyword">break</span>;

    <span class="hljs-keyword">case</span> <span class="hljs-string">"stop"</span>:
      socketInstance.close();
      <span class="hljs-keyword">break</span>;

    <span class="hljs-keyword">default</span>:
      socketManagement();
  }
}
</code></pre>
<p>So based on what message the client UI sends to the worker the appropriate function will be executed. It is pretty self-explanatory on what message which particular function should be triggered, based on the above code.</p>
<p>Now consider a scenario where we placed all the code inside <code>self.onmessage</code>.</p>
<pre><code class="lang-javascript">self.onmessage = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">e</span>)</span>{
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Worker object present "</span>, e);
    postMessage({<span class="hljs-attr">isLoading</span>: <span class="hljs-literal">true</span>, <span class="hljs-attr">data</span>: <span class="hljs-literal">null</span>});

    <span class="hljs-keyword">let</span> socket = <span class="hljs-keyword">new</span> WebSocket(<span class="hljs-string">"ws://localhost:8080"</span>);

        socket.onopen = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">e</span>) </span>{
          <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"[open] Connection established"</span>);
          <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Sending to server"</span>);
          socket.send(<span class="hljs-string">"My name is John"</span>);
        };

        socket.onmessage = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">event</span>) </span>{
          <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`[message] Data received from server: <span class="hljs-subst">${event.data}</span>`</span>);
        };

        socket.onclose = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">event</span>) </span>{
          <span class="hljs-keyword">if</span> (event.wasClean) {
            <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`[close] Connection closed cleanly, code=<span class="hljs-subst">${event.code}</span> reason=<span class="hljs-subst">${event.reason}</span>`</span>);
          } <span class="hljs-keyword">else</span> {
            <span class="hljs-comment">// e.g. server process killed or network down</span>
            <span class="hljs-comment">// event.code is usually 1006 in this case</span>
            <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'[close] Connection died'</span>);
          }
        };

            socket.onerror = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">error</span>) </span>{
              <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`[error] <span class="hljs-subst">${error.message}</span>`</span>);
            };
}
</code></pre>
<p>This would cause the following problems:</p>
<ol>
<li>On every <code>postMessage</code> call made by the client UI, there would have been a new socket instance.</li>
<li>It would have been difficult to close the socket connection.</li>
</ol>
<p>Because of these reasons, all the socket management code is written in a function <code>socketManagement</code> and catered using a switch case.</p>
<h3 id="heading-why-we-need-the-socketinstance-variable-at-the-top">Why we need the <code>socketInstance</code> variable at the top</h3>
<p>We do need a <code>socketInstance</code> variable at the top because this will store the socket instance which was previously created. It is a safe practice since no one can access this variable externally as <code>main.worker.js</code> is a separate module altogether.</p>
<h2 id="heading-communication-between-the-ui-and-the-socket-via-web-worker">Communication between the UI and the socket via web worker</h2>
<p>Now that we understand which part of the code is responsible for which section, we will take a look at how we establish a socket connection via webworkers. We'll also see how we respond via socket server to display a line chart on the UI.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/01/Untitled--1-.png" alt="Image" width="600" height="400" loading="lazy">
<em>End-to-end flow of the application</em></p>
<p><strong>NOTE:</strong> Some calls are purposefully not shown in the diagram since it will make the diagram cluttered. Make sure you refer to the code as well while referring to this diagram.</p>
<p>Now let's first understand what happens when you click on the <code>start connection</code> button on the UI:</p>
<ol>
<li>One thing to notice over here is that our web worker thread is created once the component is mounted, and is removed/terminated when the component is unmounted.</li>
<li>Once the <code>start connection</code> button is clicked, a <code>postMessage</code> call is made with <code>{connectionStatus: init}</code></li>
<li>The web worker’s <code>onmessage</code> event handler which is listening to all the message events comes to know that it has received <em>connectionStatus as init.</em> It matches the case, that is in the switch case of <code>main.worker.js</code>. It then calls the <code>createSocketInstance()</code> which returns a new socket connection at the URL: <code>ws://localhost:8080</code></li>
<li>After this a <code>socketManagement()</code> function is called which checks if the socket is created and then executes a couple of operations.</li>
<li>In this flow, since the socket connection is just established therefore, socketInstance’s <code>onpen</code> event handler is executed. </li>
<li>This will send a <code>{socketStatus: true}</code> message to the socket server. This will also send a message back to the client UI via <code>postMessage({ disableStartButton: true})</code> which tells the client UI to disable the start button.</li>
<li>Whenever the socket connection is established, then the server socket’s <code>on('connection', ()=&gt;{})</code> is invoked. So in step 3, this function is invoked at the server end.</li>
<li>Socket’s <code>on('message', () =&gt; {})</code> is invoked whenever a message is sent to the socket. So at step 6, this function is invoked at the server end. This will check if the <code>socketStatus</code> is true, and then it will start sending a random integer every 1.5 seconds to the client UI via web workers.</li>
</ol>
<p>Now that we understood how the connection is established, let's move on to understand how the socket server sends the data to the client UI:</p>
<ol>
<li>As discussed above, socket server received the message to send the data, that is a random number every 1.5 second.</li>
<li>This data is recieved on the web worker’s end using the <code>onmessage</code> handler. </li>
<li>This handler then calls the <code>postMessage</code> function and sends this data to the UI.</li>
<li>After receiving the data it appends it to an array as a <code>stockPrice</code> object. </li>
<li>This acts as a data source for our line chart component and gets updated every 1.5 seconds.</li>
</ol>
<p>Now that we understand how the connection is established, let's move on to understand how the socket server sends the data to the client UI:</p>
<ol>
<li>As discussed above, socket server recieved the message to send the data, that is a random number, every 1.5 seconds.</li>
<li>This data is recieved on the web worker’s end using the socket's <code>onmessage</code> handler. </li>
<li>This handler then calls the <code>postMessage</code> function of the web worker and sends this data to the UI.</li>
<li>After receiving the data via <code>useEffect2</code> it appends it to an array as a <code>stockPrice</code> object. </li>
<li>This acts as a data source for our line chart component and gets updated every 1.5 seconds.</li>
</ol>
<p><strong>NOTE:</strong> We are using recharts for plotting the line chart. You can find more information about it at <a target="_blank" href="https://recharts.org/en-US/">the official docs</a>.</p>
<p>Here is how our application will look in action:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/01/ezgif.com-gif-maker.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Working Example</em></p>
<h2 id="heading-summary">Summary</h2>
<p>So this was a quick introduction to what web workers are and how you can use them to solve complex problems and create better UIs. You can use web workers in your projects to handle complex UI scenarios. </p>
<p>If you want to optimize your workers, read up on the below libraries:</p>
<ul>
<li><a target="_blank" href="https://www.npmjs.com/package/comlink">comlink</a></li>
<li><a target="_blank" href="https://threads.js.org/">thread.js</a></li>
</ul>
<p>Thank you for reading!</p>
<p>Follow me on <a target="_blank" href="https://twitter.com/keurplkar">twitter</a>, <a target="_blank" href="http://github.com/keyurparalkar">github</a>, and <a target="_blank" href="https://www.linkedin.com/in/keyur-paralkar-494415107/">linkedIn</a>.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Web workers in action: why they’re helpful, and how you should use them ]]>
                </title>
                <description>
                    <![CDATA[ By The Hungry Brain Javascript is single threaded and multiple scripts can not execute at the same time. So if we execute any heavy computation task, then sometimes our page become unresponsive and the user can not do anything else until that executi... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/web-workers-in-action-2c9ff33be266/</link>
                <guid isPermaLink="false">66c3650fda3c91501890b9f8</guid>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ General Programming ]]>
                    </category>
                
                    <category>
                        <![CDATA[ tech  ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ webworker ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Wed, 12 Dec 2018 20:39:37 +0000</pubDate>
                <media:content url="https://cdn-media-1.freecodecamp.org/images/1*f1HRu4YeZDn3PAS81QjuNg.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By The Hungry Brain</p>
<p>Javascript is single threaded and multiple scripts can not execute at the same time. So if we execute any heavy computation task, then sometimes our page become unresponsive and the user can not do anything else until that execution gets completed.</p>
<p>For example:</p>
<pre><code class="lang-js">average = <span class="hljs-function">(<span class="hljs-params">numbers</span>) =&gt;</span> {
    <span class="hljs-keyword">let</span> startTime = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>().getTime();
    <span class="hljs-keyword">let</span> len = numbers,
        sum = <span class="hljs-number">0</span>,
        i;

    <span class="hljs-keyword">if</span> (len === <span class="hljs-number">0</span>) {
        <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;
    }

    <span class="hljs-keyword">for</span> (i = <span class="hljs-number">0</span>; i &lt; len; i++) {
        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'i :: '</span>, i)
        sum += i;
    }

    <span class="hljs-keyword">let</span> endTime = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>().getTime();
    alert(<span class="hljs-string">'Average - '</span>, sum / len);
}

hello = <span class="hljs-function">() =&gt;</span> {
    alert(<span class="hljs-string">"Hello World !!"</span>);
}

<span class="hljs-comment">/*
Paste the above code in browser dev tool console
and try to call average(10000) and hello one by one
*/</span>
</code></pre>
<p>In the above example, if you call <em>average</em> before the <em>hello</em> method, then your page will become unresponsive and you won’t be able to click on <em>Hello</em> until the execution of <em>average</em> gets completed.</p>
<p>You can see that when <em>average</em> is called with 10000 as input first, it took ~1.82 seconds. For that amount of time the page becomes unresponsive and you were not able to click on the hello button.</p>
<h3 id="heading-asynchronous-programming">Asynchronous Programming</h3>
<p>Javascript gives the way to developers to write <strong>async code</strong>. By writing asynchronous code you can avoid this kind of issue with in your application as it enables your app UI to be responsive, by “scheduling” parts of the code to be executed a bit later in the event loop.</p>
<p>A good example of async programming is <code>XHR request</code>, in this we hit an API asynchronously and while waiting for the response, other code can be executed. But this is limited to certain use cases related to web APIs mostly.</p>
<p>Another way of writing async code is by using <code>setTimeout</code> method. In some cases, you can achieve good results in unblocking the UI from longer-running computations by using <code>setTimeout</code>. For example, by batching a complex computation in separate <code>setTimeout</code> calls.</p>
<p>For example:</p>
<pre><code class="lang-js">average = <span class="hljs-function">(<span class="hljs-params">numbers</span>) =&gt;</span> {
    <span class="hljs-keyword">let</span> startTime = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>().getTime();
    <span class="hljs-keyword">var</span> len = numbers,
        sum = <span class="hljs-number">0</span>,
        i;

    <span class="hljs-keyword">if</span> (len === <span class="hljs-number">0</span>) {
        <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;
    }

    <span class="hljs-keyword">let</span> calculateSumAsync = <span class="hljs-function">(<span class="hljs-params">i</span>) =&gt;</span> {
        <span class="hljs-keyword">if</span> (i &lt; len) {
            <span class="hljs-comment">// Put the next function call on the event loop.</span>
            <span class="hljs-built_in">setTimeout</span>(<span class="hljs-function">() =&gt;</span> {
                sum += i;
                calculateSumAsync(i + <span class="hljs-number">1</span>);
            }, <span class="hljs-number">0</span>);
        } <span class="hljs-keyword">else</span> {
            <span class="hljs-comment">// The end of the array is reached so we're invoking the alert.</span>
            <span class="hljs-keyword">let</span> endTime = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>().getTime();
            alert(<span class="hljs-string">'Average - '</span>, sum / len);
        }
    };

    calculateSumAsync(<span class="hljs-number">0</span>);
};

hello = <span class="hljs-function">() =&gt;</span> {
    alert(<span class="hljs-string">'Hello World !!'</span>)
};
</code></pre>
<p>In this example, you can see that after you click on the <em>Calculate Average</em> button, you can still click on the <em>Hello</em> button (which in turn shows an alert message). This way of programming is surely non-blocking but takes too much time, and is not feasible in real world applications.</p>
<p>Here, for the same input 10000, it took ~60 seconds, which is very inefficient.</p>
<p><strong>So, how do we solve these kinds of issues efficiently?</strong></p>
<p>The answer is <strong>Web Workers.</strong></p>
<h3 id="heading-what-are-web-workers">What are web workers ?</h3>
<p>Web workers in Javascript are a great way to execute some task which is very laborious and time taking into a thread separate from the main thread. They run in background and perform tasks without interfering with the user interface.</p>
<p>Web Workers are not the part of JavaScript, they’re a browser feature which can be accessed through JavaScript.</p>
<p>Web workers are created by a constructor function <strong>Worker()</strong> which runs a named JS file.</p>
<pre><code class="lang-js"><span class="hljs-comment">// create a dedicated web worker</span>
<span class="hljs-keyword">const</span> myWorker = <span class="hljs-keyword">new</span> Worker(<span class="hljs-string">'worker.js'</span>);
</code></pre>
<p>If the specified file exists then it will be downloaded asynchronously and if not then worker will fail silently, so your application will still work in case of 404.</p>
<p>We will learn more about creation and working of web workers in the next section.</p>
<p>Worker thread has its own context and therefore you can only access selected features inside a worker thread like - web sockets, indexed DB.</p>
<p>There are some <strong>restrictions</strong> with web workers -</p>
<ol>
<li>You can't directly manipulate the DOM from inside a worker.</li>
<li>You can not use some default methods and properties of the window object since window object is not available inside a worker thread.</li>
<li>The context inside the worker thread can be accessed via <strong><em>DedicatedWorkerGlobalScope or SharedWorkerGlobalScope</em></strong> depending upon the usage.</li>
</ol>
<h3 id="heading-features-of-web-workers">Features of Web Workers</h3>
<p>There are two types of web workers -</p>
<ol>
<li><strong>Dedicated web worker</strong> - A dedicated worker is only accessible by the script that called it.</li>
<li><strong>Shared web worker</strong> - A shared worker is accessible by multiple scripts — even if they are being accessed by different windows, iframes or even workers.</li>
</ol>
<p>Let us discuss more about those two types of web workers -</p>
<h4 id="heading-creation-of-a-web-worker">Creation of a web worker</h4>
<p>Creation is pretty much same for both a Dedicated and Shared web worker.</p>
<p><strong>Dedicated web worker</strong></p>
<ul>
<li>Creating a new worker is simple, just call the Worker constructor and pass the path of the script you want to execute as worker.</li>
</ul>
<pre><code class="lang-js"><span class="hljs-comment">// create a dedicated web worker</span>
<span class="hljs-keyword">const</span> myWorker = <span class="hljs-keyword">new</span> Worker(<span class="hljs-string">'worker.js'</span>);
</code></pre>
<p><strong>Shared web worker :</strong></p>
<ul>
<li>Creating a new shared worker is pretty much the same as that of dedicated worker, but with a different constructor name.</li>
</ul>
<pre><code class="lang-js"><span class="hljs-comment">// creating a shared web worker</span>
<span class="hljs-keyword">const</span> mySharedWorker = <span class="hljs-keyword">new</span> SharedWorker(<span class="hljs-string">'worker.js'</span>);
</code></pre>
<h4 id="heading-communication-between-main-and-worker-thread">Communication between main and worker thread</h4>
<p>Communication between main thread and worker thread happens via <em>postMessage</em> method and <em>onmessage</em> event handler.</p>
<p><strong>Dedicated web worker</strong><br>In case of a dedicated web worker, communication system is simple. You just need to use postMessage method whenever you want to send message to the worker.</p>
<pre><code class="lang-js">(<span class="hljs-function">() =&gt;</span> {
  <span class="hljs-comment">// new worker</span>
  <span class="hljs-keyword">let</span> myWorker = <span class="hljs-keyword">new</span> Worker(<span class="hljs-string">'worker.js'</span>);

  <span class="hljs-comment">// event handler to recieve message from worker</span>
  myWorker.onmessage = <span class="hljs-function">(<span class="hljs-params">e</span>) =&gt;</span> {
    <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'time'</span>).innerHTML = <span class="hljs-string">`<span class="hljs-subst">${e.data.time}</span> seconds`</span>;
  };

  <span class="hljs-keyword">let</span> average = <span class="hljs-function">(<span class="hljs-params">numbers</span>) =&gt;</span> {
    <span class="hljs-comment">// sending message to web worker with an argument</span>
    myWorker.postMessage(numbers);
  }

  average(<span class="hljs-number">1000</span>);
})();
</code></pre>
<p>And inside a web worker you can respond when the message is received by writing an event handler block like this:</p>
<pre><code class="lang-js">onmessage = <span class="hljs-function">(<span class="hljs-params">e</span>) =&gt;</span> {
    <span class="hljs-keyword">let</span> numbers = e.data;
    <span class="hljs-keyword">let</span> startTime = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>().getTime();
    <span class="hljs-keyword">let</span> len = numbers,
        sum = <span class="hljs-number">0</span>,
        i;

    <span class="hljs-keyword">if</span> (len === <span class="hljs-number">0</span>) {
        <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;
    }

    <span class="hljs-keyword">for</span> (i = <span class="hljs-number">0</span>; i &lt; len; i++) {
        sum += i;
    }

    <span class="hljs-keyword">let</span> endTime = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>().getTime();
    postMessage({<span class="hljs-attr">average</span>: sum / len, <span class="hljs-attr">time</span>: ((endTime - startTime) / <span class="hljs-number">1000</span>)})
};
</code></pre>
<p>The <code>onmessage</code> handler allows to run some code whenever a message is received. </p>
<p>Here we are calculating average of numbers and then use <code>postMessage()</code> again, to post the result back to the main thread.</p>
<p>As you can see on <em>line 6 in main.js</em> we have used onmessage event on the worker instance. So whenever worker thread use postMessage, onmessage in the main thread gets triggered.</p>
<ul>
<li><strong>Shared web worker</strong><br>In case of a shared web worker, communication system is little different. As one worker is shared between multiple scripts, we need to communicate via the port object of worker instance. This is done implicitly in case of dedicated workers. You need to use postMessage method whenever you want to send message to the worker.</li>
</ul>
<pre><code class="lang-js">(<span class="hljs-function">() =&gt;</span> {
  <span class="hljs-comment">// new worker</span>
  <span class="hljs-keyword">let</span> myWorker = <span class="hljs-keyword">new</span> Worker(<span class="hljs-string">'worker.js'</span>);

  <span class="hljs-comment">// event handler to recieve message from worker</span>
  myWorker.onmessage = <span class="hljs-function">(<span class="hljs-params">e</span>) =&gt;</span> {
    <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'time'</span>).innerHTML = <span class="hljs-string">`<span class="hljs-subst">${e.data.time}</span> seconds`</span>;
  };

  <span class="hljs-keyword">let</span> average = <span class="hljs-function">(<span class="hljs-params">numbers</span>) =&gt;</span> {
    <span class="hljs-comment">// sending message to web worker with an argument</span>
    myWorker.postMessage(numbers);
  }

  average(<span class="hljs-number">1000</span>);
</code></pre>
<p>Inside a web worker (<em>main-shared-worker.js</em>) it is a little complex. First, we use an <code>onconnect</code> handler to fire code when a connection to the port happens (<em>line 2</em>).<br>We use the <code>ports</code> attribute of this event object to grab the port and store it in a variable (<em>line 4</em>).<br>Next, we add a <code>message</code> handler on the port to do the calculation and return the result to the main thread (<em>line 7 and line 25</em>) like this:</p>
<pre><code class="lang-js">onmessage = <span class="hljs-function">(<span class="hljs-params">e</span>) =&gt;</span> {
    <span class="hljs-keyword">let</span> numbers = e.data;
    <span class="hljs-keyword">let</span> startTime = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>().getTime();
    <span class="hljs-keyword">let</span> len = numbers,
        sum = <span class="hljs-number">0</span>,
        i;

    <span class="hljs-keyword">if</span> (len === <span class="hljs-number">0</span>) {
        <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;
    }

    <span class="hljs-keyword">for</span> (i = <span class="hljs-number">0</span>; i &lt; len; i++) {
        sum += i;
    }

    <span class="hljs-keyword">let</span> endTime = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>().getTime();
    postMessage({<span class="hljs-attr">average</span>: sum / len, <span class="hljs-attr">time</span>: ((endTime - startTime) / <span class="hljs-number">1000</span>)})
};
</code></pre>
<h4 id="heading-termination-of-a-web-worker">Termination of a web worker</h4>
<p>If you need to immediately terminate a running worker from the main thread, you can do so by calling the worker’s <em>terminate</em> method:</p>
<pre><code class="lang-js"><span class="hljs-comment">// terminating a web worker instance</span>
myWorker.terminate();
</code></pre>
<p>The worker thread is killed immediately without an opportunity to complete its operations.</p>
<h3 id="heading-spawning-of-web-worker">Spawning of web worker</h3>
<p>Workers may spawn more workers if they wish. But they must be hosted within the same origin as the parent page.</p>
<h3 id="heading-importing-scripts">Importing Scripts</h3>
<p>Worker threads have access to a global function, <code>importScripts()</code>, which lets them import scripts.</p>
<pre><code class="lang-js">importScripts();                         <span class="hljs-comment">/* imports nothing */</span>
importScripts(<span class="hljs-string">'foo.js'</span>);                 <span class="hljs-comment">/* imports just "foo.js" */</span>
importScripts(<span class="hljs-string">'foo.js'</span>, <span class="hljs-string">'bar.js'</span>);       <span class="hljs-comment">/* imports two scripts */</span>
importScripts(<span class="hljs-string">'//example.com/hello.js'</span>); <span class="hljs-comment">/* You can import scripts from other origins */</span>
</code></pre>
<h3 id="heading-working-demo">Working Demo</h3>
<p>We have discussed some of the approaches above to achieve async programming so that our UI doesn’t get blocked due to any heavy computational task. But there are some limitations to those approaches. So we can use web workers to solve these kind of problems efficiently.</p>
<blockquote>
<p><em>Click <a target="_blank" href="https://bhushangoel.github.io/webworker-demo-1/">here</a> to run this live demo.</em></p>
</blockquote>
<p>Here, you will see 3 sections:</p>
<ol>
<li><strong>Blocking Code</strong>:<br>When you click on <em>calculate average</em>, the loader does not display and after some time you see the final result and time taken. This is because as soon as the <em>average method</em> gets called, I have triggered the <em>showLoader</em> method also. But since JS is single threaded, it won’t execute showLoader until the execution of average gets completed. So, you won’t be able to see the loader in this case ever.</li>
<li><strong>Async Code</strong>:<br>In this I tried to achieve the same functionality by using the setTimeout method and putting every function execution into an event loop. You will see the loader in this case, but the response takes time as compared to the method defined above.</li>
<li><strong>Web worker</strong>:<br>This is an example of using a web worker. In this you will see the loader as soon as you click on calculate average and you will get a response in the same time as of method 1, for the same number.</li>
</ol>
<p>You can access the source code for the same <a target="_blank" href="https://github.com/bhushangoel/webworker-demo-1/tree/master">here</a>.</p>
<h3 id="heading-advanced-concepts">Advanced concepts</h3>
<p>There are some advanced concepts related to web workers. We won’t be discussing them in detail, but its good to know about them.</p>
<ol>
<li><strong>Content Security Policy —</strong><br>Web workers have their own execution context independent of the document that created them and because of this reason they are not governed by the Content Security Policy of the parent thread/worker.<br>The exception to this is if the worker script's origin is a globally unique identifier (for example, if its URL has a scheme of data or blob). In this case, the worker inherit the content security policy of the document or worker that created it.</li>
<li><strong>Transferring data to and from workers</strong> —<br>Data passed between main and worker thread is <strong>copied</strong> and not shared. Objects are serialized as they're handed to the worker, and subsequently, de-serialized on the other end. The page and worker <strong>do not share the same instance</strong>, so the end result is that <strong>a duplicate</strong> is created on each end.<br>Browsers implemented <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm"><strong>Structured Cloning</strong></a> algorithm to achieve this.</li>
<li><strong>Embedded workers —</strong><br>You can also embed the code of worker inside a web page (html). For this you need to add a script tag without a src attribute and assign a non-executable MIME type to it, like this:</li>
</ol>
<pre><code class="lang-js">&lt;!DOCTYPE html&gt;
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">html</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">"UTF-8"</span> /&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>embedded worker<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
  <span class="hljs-comment">&lt;!--script tag with un-identified MIME and w/o src attr --&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text/js-worker"</span>&gt;</span><span class="javascript">
    <span class="hljs-comment">// This script WON'T be parsed by JS engines because its MIME type is text/js-worker.</span>
    <span class="hljs-keyword">var</span> myVar = <span class="hljs-string">'Hello World!'</span>;

    <span class="hljs-comment">// worker block</span>
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">onmessage</span>(<span class="hljs-params">e</span>) </span>{
      <span class="hljs-comment">// worker code</span>
    }
  </span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span></span>
</code></pre>
<p>There are a lot of use cases to use web workers in our application. I have just discussed a small scenario. Hope this helps you understand the concept of web workers.</p>
<h4 id="heading-links">[Links]</h4>
<p>Github Repo : <a target="_blank" href="https://github.com/bhushangoel/webworker-demo-1">https://github.com/bhushangoel/webworker-demo-1</a> Web worker in action : <a target="_blank" href="https://bhushangoel.github.io/webworker-demo-1/">https://bhushangoel.github.io/webworker-demo-1/</a>JS demo showcase : <a target="_blank" href="https://bhushangoel.github.io/">https://bhushangoel.github.io/</a></p>
<p>Thank you for reading.</p>
<p>Happy Learning :)</p>
<p><em>Originally published at <a target="_blank" href="https://www.thehungrybrain.com/home/web-workers">www.thehungrybrain.com</a>.</em></p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
