Menu
×
   ❮     
HTML CSS JAVASCRIPT SQL PYTHON JAVA PHP W3.CSS C C++ C# HOW TO BOOTSTRAP REACT MYSQL JQUERY EXCEL XML DJANGO NUMPY PANDAS NODEJS DSA TYPESCRIPT ANGULAR ANGULARJS GIT POSTGRESQL MONGODB ASP AI R GO KOTLIN SWIFT SASS VUE GEN AI SCIPY AWS CYBERSECURITY DATA SCIENCE INTRO TO PROGRAMMING INTRO TO HTML & CSS BASH RUST TOOLS

JS Tutorial

JS Home JS Introduction JS Where To JS Output JS Syntax JS Operators JS If Conditions JS Loops JS Strings JS Numbers JS Functions JS Timers JS Objects JS Scope JS Dates JS Temporal  New JS Arrays JS Sets JS Maps JS Iterations JS Math JS RegExp JS Data Types JS Errors JS Debugging JS Style Guide JS Reference JS Projects  New JS Versions JS HTML DOM JS HTML Events JS HTML First

JS Advanced

JS Functions JS Objects JS Classes JS JSON JS Asynchronous JS Modules JS Meta & Proxy JS Typed Arrays JS DOM Navigation JS Browser API JS Web API JS Graphics

Old Technologies

JS AJAX JS jQuery JS JSONP

JS Examples

JS Examples

JavaScript Web Workers

Until now, all examples in this tutorial run on the browser's main thread.

Asynchronous programming keeps applications responsive while waiting for:

  • Timers
  • User input
  • Network requests

However, long-running calculations can still block the main thread and make a page unresponsive.

Web Workers solve this by running JavaScript in a separate thread.

Why Web Workers?

JavaScript normally executes one task at a time.

If a task takes a long time to finish, the browser cannot respond to user input until the task has completed.

This can make a page appear frozen.

The page becomes unresponsive until the calculation finishes.

Example

A long-running calculation freezes the page.

function calculate() {
  let total = 0;
  for (let i = 0; i < 5e9; i++) {
    total += i;
  }
  return total;
}

myDisplayer("Calculating...");

let result = calculate();

myDisplayer(result);
Try it Yourself »

Can Asynchronous Programming Help?

Timers, Promises, and async/await do not solve this problem.

They all execute JavaScript on the same main thread.

If the thread is busy performing calculations, the browser must still wait.

Example

myDisplayer("Start");

setTimeout(function () {
  myDisplayer("Timer")}, 1000);

let i = 5e9;
while (--i > 0);

myDisplayer("Finished");

The timer finishes after one second, but its callback cannot run until the loop has completed.

Try it Yourself »

What Is a Web Worker?

A Web Worker runs JavaScript in a separate thread.

While the worker performs calculations, the browser's main thread remains free to respond to user input.

The main thread and the worker communicate by sending messages.


Browser Support

Before creating a worker, check whether the browser supports Web Workers.

Example

if (typeof(Worker) !== "undefined") {
  myDisplayer("Web Workers are supported.");
} else {
  myDisplayer("Web Workers are not supported.");
}
Try it Yourself »


Creating a Worker

Create a worker with the new Worker() constructor.

const worker = new Worker("worker.js");

The file passed to the constructor contains the code that will run in the worker thread.


Receiving Messages

The main thread receives messages with the onmessage event.

Example

const worker = new Worker("worker.js");

worker.onmessage = function(event) {
  myDisplayer(event.data);
};
Try it Yourself »

Sending Messages

The main thread sends data to the worker with postMessage().

Main page:

const worker = new Worker("worker.js");

worker.postMessage(25);

worker.js

onmessage = function(event) {
  postMessage(event.data * event.data);
}

Result

625

Complete Example

Example

const worker = new Worker("worker.js");

worker.onmessage = function(event) {
  myDisplayer(event.data);
};

worker.postMessage(1000000);

worker.js

onmessage = function(event) {
  let sum = 0;
  for (let i = 0; i <= event.data; i++) {
    sum += i;
  }
  postMessage(sum);
};

Note

The calculation happens in the worker.

The page remains responsive.


Part 1 Summary

  • Web Workers run JavaScript in a separate thread.
  • Workers keep the main thread responsive during long-running calculations.
  • Create a worker with new Worker().
  • Workers communicate using postMessage().
  • Receive messages with the onmessage event.

Web Workers Part 2


Passing Data to a Worker

The postMessage() method can send numbers, strings, arrays, and objects.

The browser copies the data and sends the copy to the worker.

Main page:

const worker = new Worker("worker.js");

const person = {
  name: "John",
  age: 30
};

worker.postMessage(person);

worker.onmessage = function(event) {
  document.getElementById("demo").innerHTML = event.data;
};

worker.js:

onmessage = function(event) {
  const person = event.data;
  const message = person.name + " is " + person.age + " years old.";
  postMessage(message);
};

Note

The worker receives the object through event.data.


Worker Progress Messages

A worker can send more than one message.

This makes it possible to report progress while a long calculation is running.

Main page:

const worker = new Worker("worker.js");

worker.onmessage = function(event) {
  document.getElementById("demo").innerHTML = event.data;
};

worker.postMessage(100000000);

worker.js:

onmessage = function(event) {
  const limit = event.data;
  let total = 0;
  for (let i = 0; i <= limit; i++) {
    total += i;
    if (i % 10000000 === 0) {
      postMessage("Progress: " + Math.round(i / limit * 100) + "%");
    }
  }
  postMessage("Result: " + total);
};

Note

The worker sends progress messages without blocking the main page.

The main thread can still respond to buttons, scrolling, and other user actions while the worker is running.


Starting a Worker

A worker can be created when the user starts a task.

Saving the worker in a variable makes it possible to stop or reuse the reference later.

Example

let worker;

function startWorker() {
  worker = new Worker("worker.js");

  worker.onmessage = function(event) {
    document.getElementById("demo").innerHTML = event.data;
  };

  worker.postMessage(100000000);
}

Stopping a Worker

Use the terminate() method to stop a worker immediately.

worker.terminate();

Note

After a worker has been terminated, it cannot be started again.

Create a new worker if the task must run again.

Example

let worker;

function startWorker() {
  if (worker) {
    return;
  }

  worker = new Worker("worker.js");

  worker.onmessage = function(event) {
    document.getElementById("demo").innerHTML = event.data;
  };

  worker.postMessage(100000000);
}

function stopWorker() {
  if (worker) {
    worker.terminate();
    worker = undefined;
    document.getElementById("demo").innerHTML = "Worker stopped";
  }
}

Complete Start and Stop Example

This example starts a long calculation in a worker.

The worker reports progress and can be stopped before it finishes.

Example

Main page:

<button onclick="startWorker()">Start Worker</button>
<button onclick="stopWorker()">Stop Worker</button>

Ready

let worker;

function startWorker() {
  if (worker) {
    return;
  }

  document.getElementById("demo").innerHTML = "Starting...";

  worker = new Worker("worker.js");

  worker.onmessage = function(event) {
    document.getElementById("demo").innerHTML = event.data;

    if (event.data.startsWith("Result:")) {
      worker.terminate();
      worker = undefined;
    }
  };

  worker.postMessage(100000000);
}

function stopWorker() {
  if (worker) {
    worker.terminate();
    worker = undefined;
    document.getElementById("demo").innerHTML = "Worker stopped";
  }
}

worker.js:

onmessage = function(event) {
  const limit = event.data;
  let total = 0;

  for (let i = 0; i <= limit; i++) {
    total += i;

    if (i % 10000000 === 0) {
      const percent = Math.round(i / limit * 100);
      postMessage("Progress: " + percent + "%");
    }
  }

  postMessage("Result: " + total);
};

Worker Errors

Use the onerror event to handle errors from a worker.

Example

const worker = new Worker("worker.js");

worker.onerror = function(error) {
  document.getElementById("demo").innerHTML =
  "Error: " + error.message;
};

The error object can contain information such as the message, filename, and line number.

Property Description
message The error message.
filename The file where the error occurred.
lineno The line number where the error occurred.
colno The column number where the error occurred.

Handling Errors Inside a Worker

A worker can also catch its own errors and send a message to the main thread.

Main page:

worker.onmessage = function(event) {
  if (event.data.error) {
    document.getElementById("demo").innerHTML = event.data.error;
  } else {
    document.getElementById("demo").innerHTML = event.data.result;
  }
};

worker.js:

onmessage = function(event) {
  try {
    const result = calculate(event.data);
    postMessage({result: result});
  } catch(error) {
    postMessage({error: error.message});
  }
};

Closing a Worker from Inside

A worker can stop itself by calling close().

postMessage("Finished");
close();

The close() function stops the worker after the current code finishes.

Method Called From Description
worker.terminate() Main thread Stops the worker immediately.
close() Worker thread Lets the worker stop itself.

Creating a New Worker

A terminated worker cannot be restarted.

Create a new Worker object to run the task again.

worker = new Worker("worker.js");

Set the worker variable to undefined or null after termination.

This makes it easier to know whether a worker is currently running.


One Worker or Many Workers?

A page can create more than one worker.

const worker1 = new Worker("worker1.js");
const worker2 = new Worker("worker2.js");

Each worker runs in a separate thread.

However, creating many workers can use significant memory and processing power.

Use workers only for tasks that benefit from running in a separate thread.

Do not create a new worker for every small calculation.


Worker Lifecycle

A Web Worker normally follows these steps:

  1. The main page creates the worker.
  2. The main page sends data with postMessage().
  3. The worker receives the data.
  4. The worker performs its task.
  5. The worker sends results back.
  6. The main page uses the result.
  7. The worker is terminated when it is no longer needed.
Create Worker
      |
      |
      v
Send Data
      |
      |
      v
Worker Calculates
      |
      |
      v
Send Result
      |
      |
      v
Stop Worker

Part 2 Summary

  • Workers can receive strings, numbers, arrays, and objects.
  • A worker can send multiple messages to report progress.
  • Use terminate() to stop a worker from the main thread.
  • Use close() to stop a worker from inside the worker.
  • Use onerror to handle worker errors.
  • A terminated worker cannot be restarted.
  • Create a new Worker object to run the task again.

What Can a Worker Do?

A Web Worker runs JavaScript just like the main thread.

It can perform calculations, use timers, make network requests, and work with JavaScript objects.

This makes workers useful for CPU-intensive tasks that would otherwise block the page.

Task Supported
JavaScript calculations Yes
Loops Yes
Functions Yes
Arrays and Objects Yes
Promises Yes
fetch() Yes
setTimeout() Yes
setInterval() Yes

What Can't a Worker Do?

A worker cannot access the web page.

Only the main thread can modify the DOM.

Feature Available
document No
window No
HTML elements No
DOM events No
alert() No

A worker performs calculations.

The main thread updates the user interface.


Updating the Page

A worker cannot update HTML directly.

Instead, it sends the result back to the main thread.

Example

worker.js:

postMessage("Finished");

Main page:

worker.onmessage = function(event) {
  document.getElementById("demo").innerHTML = event.data;
};

Using fetch() Inside a Worker

A worker can download data from a server.

The downloaded data can then be sent back to the main thread.

Example

worker.js:

async function loadData() {
  const response = await fetch("data.txt");
  const text = await response.text();
  postMessage(text);
}

loadData();
Try it Yourself »

Using Timers

Workers support JavaScript timers.

Example

setInterval(function() {
  postMessage(new Date().toLocaleTimeString());
}, 1000);

When Should You Use a Worker?

Workers are useful for long-running JavaScript tasks.

Good Uses
Large mathematical calculations
Image processing
Video processing
Searching large datasets
Compression and decompression
Encryption
Artificial Intelligence
Scientific calculations

When Should You Not Use a Worker?

Workers are not needed for small tasks.

Creating a worker takes time and uses memory.

Simple calculations often run faster on the main thread.

Do not create a worker unless the task is large enough to benefit from another thread.


Asynchronous Programming vs Web Workers

Asynchronous programming and Web Workers solve different problems.

Asynchronous Programming Web Workers
One JavaScript thread Multiple JavaScript threads
Good for waiting Good for calculating
Uses Promises and async/await Uses Worker objects
Network requests CPU-intensive tasks
Does not block while waiting Does not block while calculating

Asynchronous programming keeps JavaScript busy while waiting.

Web Workers keep the browser responsive while JavaScript is calculating.


Common Mistakes

Trying to Access the DOM

This will fail:

document.getElementById("demo").innerHTML = "Hello";

Workers must use postMessage() instead.

Creating Too Many Workers

Workers consume memory and CPU resources.

Create only the workers you need.

Forgetting to Stop Workers

Terminate workers when they are no longer needed.

worker.terminate();

Summary

  • Web Workers run JavaScript on a separate thread.
  • Workers keep the main thread responsive during long calculations.
  • Workers communicate with the main thread using postMessage().
  • Workers cannot access the DOM.
  • Workers support Promises, fetch(), and timers.
  • Use workers for CPU-intensive tasks.
  • Use asynchronous programming for waiting on operations such as timers and network requests.

Congratulations!

You have completed the JavaScript Asynchronous Programming tutorial.

You have learned how JavaScript handles asynchronous operations using:

  • Callbacks
  • Promises
  • async / await
  • The Event Loop
  • Timers
  • Fetch API
  • AbortController
  • Web Workers

You are now ready to build responsive JavaScript applications that can perform asynchronous operations and long-running calculations efficiently.



×

Contact Sales

If you want to use W3Schools services as an educational institution, team or enterprise, send us an e-mail:
sales@w3schools.com

Report Error

If you want to report an error, or if you want to make a suggestion, send us an e-mail:
help@w3schools.com

W3Schools is optimized for learning and training. Examples might be simplified to improve reading and learning. Tutorials, references, and examples are constantly reviewed to avoid errors, but we cannot warrant full correctness of all content. While using W3Schools, you agree to have read and accepted our terms of use, cookies and privacy policy.

Copyright 1999-2026 by Refsnes Data. All Rights Reserved. W3Schools is Powered by W3.CSS.

-->