Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix globals, part 13: queueMicrotask() #35929

Merged
merged 2 commits into from
Sep 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion files/en-us/_redirects.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10262,7 +10262,7 @@
/en-US/docs/Web/API/WindowOrWorkerGlobalScope/indexedDB /en-US/docs/Web/API/Window/indexedDB
/en-US/docs/Web/API/WindowOrWorkerGlobalScope/isSecureContext /en-US/docs/Web/API/Window/isSecureContext
/en-US/docs/Web/API/WindowOrWorkerGlobalScope/origin /en-US/docs/Web/API/Window/origin
/en-US/docs/Web/API/WindowOrWorkerGlobalScope/queueMicrotask /en-US/docs/Web/API/queueMicrotask
/en-US/docs/Web/API/WindowOrWorkerGlobalScope/queueMicrotask /en-US/docs/Web/API/Window/queueMicrotask
/en-US/docs/Web/API/WindowOrWorkerGlobalScope/rejectionhandled_event /en-US/docs/Web/API/Window/rejectionhandled_event
/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setInterval /en-US/docs/Web/API/setInterval
/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout /en-US/docs/Web/API/setTimeout
Expand Down Expand Up @@ -10709,6 +10709,7 @@
/en-US/docs/Web/API/onMSVideoOptimalLayoutChanged_ /en-US/docs/Web/API/HTMLVideoElement
/en-US/docs/Web/API/origin /en-US/docs/Web/API/Window/origin
/en-US/docs/Web/API/performance_property /en-US/docs/Web/API/Window/performance
/en-US/docs/Web/API/queueMicrotask /en-US/docs/Web/API/Window/queueMicrotask
/en-US/docs/Web/API/range.cloneContents /en-US/docs/Web/API/range/cloneContents
/en-US/docs/Web/API/range.cloneRange /en-US/docs/Web/API/range/cloneRange
/en-US/docs/Web/API/range.collapse /en-US/docs/Web/API/range/collapse
Expand Down
20 changes: 10 additions & 10 deletions files/en-us/_wikihistory.json
Original file line number Diff line number Diff line change
Expand Up @@ -68208,6 +68208,16 @@
"JesseW"
]
},
"Web/API/Window/queueMicrotask": {
"modified": "2020-10-15T22:21:06.789Z",
"contributors": [
"Kaiido",
"chrisdavidmills",
"Sheppy",
"zbjornson",
"DomenicDenicola"
]
},
"Web/API/Window/rejectionhandled_event": {
"modified": "2020-10-15T21:44:33.123Z",
"contributors": [
Expand Down Expand Up @@ -71518,16 +71528,6 @@
"adria"
]
},
"Web/API/queueMicrotask": {
"modified": "2020-10-15T22:21:06.789Z",
"contributors": [
"Kaiido",
"chrisdavidmills",
"Sheppy",
"zbjornson",
"DomenicDenicola"
]
},
"Web/API/setInterval": {
"modified": "2020-12-09T23:19:41.310Z",
"contributors": [
Expand Down
2 changes: 1 addition & 1 deletion files/en-us/mozilla/firefox/releases/69/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ This article provides information about the changes in Firefox 69 that will affe
#### New APIs

- The [Resize Observer API](/en-US/docs/Web/API/Resize_Observer_API) is supported by default ([Firefox bug 1543839](https://bugzil.la/1543839)).
- The Microtask API ({{domxref("queueMicrotask()")}}) has been implemented ([Firefox bug 1480236](https://bugzil.la/1480236)).
- The Microtask API ({{domxref("Window.queueMicrotask()")}} and {{domxref("WorkerGlobalScope.queueMicrotask()")}}) has been implemented ([Firefox bug 1480236](https://bugzil.la/1480236)).

#### DOM

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ JavaScript is an inherently single-threaded language. It was designed in an era

As time passed, of course, we know that computers have evolved into powerful multi-core systems, and JavaScript has become one of the most prolifically-used languages in the computing world. A vast number of the most popular applications are based at least in part on JavaScript code. To support this, it was necessary to find ways to allow for projects to escape the limitations of a single-threaded language.

Starting with the addition of timeouts and intervals as part of the Web API ({{domxref("setTimeout()")}} and {{domxref("setInterval()")}}), the JavaScript environment provided by Web browsers has gradually advanced to include powerful features that enable scheduling of tasks, multi-threaded application development, and so forth. To understand where `queueMicrotask()` comes into play here, it's helpful to understand how the JavaScript runtime operates when scheduling and running code.
Starting with the addition of timeouts and intervals as part of the Web API ({{domxref("setTimeout()")}} and {{domxref("setInterval()")}}), the JavaScript environment provided by Web browsers has gradually advanced to include powerful features that enable scheduling of tasks, multi-threaded application development, and so forth. To understand where {{domxref("Window.queueMicrotask()", "queueMicrotask()")}} comes into play here, it's helpful to understand how the JavaScript runtime operates when scheduling and running code.

## JavaScript execution contexts

Expand Down Expand Up @@ -140,12 +140,12 @@ This is further alleviated by using [asynchronous JavaScript](/en-US/docs/Learn/

Microtasks are another solution to this problem, providing a finer degree of access by making it possible to schedule code to run before the next iteration of the event loop begins, instead of having to wait until the next one.

The microtask queue has been around for a while, but it's historically been used only internally in order to drive things like promises. The addition of `queueMicrotask()`, exposing it to web developers, creates a unified queue for microtasks which is used wherever it's necessary to have the ability to schedule code to run safely when there are no execution contexts left on the JavaScript execution context stack. Across multiple instances and across all browsers and JavaScript runtimes, a standardized microqueue mechanism means these microtasks will operate reliably in the same order, thus avoiding potentially difficult to find bugs.
The microtask queue has been around for a while, but it's historically been used only internally in order to drive things like promises. The addition of {{domxref("Window.queueMicrotask()", "queueMicrotask()")}}, exposing it to web developers, creates a unified queue for microtasks which is used wherever it's necessary to have the ability to schedule code to run safely when there are no execution contexts left on the JavaScript execution context stack. Across multiple instances and across all browsers and JavaScript runtimes, a standardized microqueue mechanism means these microtasks will operate reliably in the same order, thus avoiding potentially difficult to find bugs.

## See also

- [Microtask guide](/en-US/docs/Web/API/HTML_DOM_API/Microtask_guide)
- {{domxref("queueMicrotask()")}}
- {{domxref("Window.queueMicrotask()")}}
- [The Event Loop](/en-US/docs/Web/JavaScript/Event_loop)
- [Asynchronous JavaScript](/en-US/docs/Learn/JavaScript/Asynchronous)
- [Introducing asynchronous JavaScript](/en-US/docs/Learn/JavaScript/Asynchronous/Introducing)
Expand Down
12 changes: 6 additions & 6 deletions files/en-us/web/api/html_dom_api/microtask_guide/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ A **microtask** is a short function which is executed after the function or prog

This event loop may be either the browser's main event loop or the event loop driving a [web worker](/en-US/docs/Web/API/Web_Workers_API). This lets the given function run without the risk of interfering with another script's execution, yet also ensures that the microtask runs before the user agent has the opportunity to react to actions taken by the microtask.

JavaScript [promises](/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) and the [Mutation Observer API](/en-US/docs/Web/API/MutationObserver) both use the microtask queue to run their callbacks, but there are other times when the ability to defer work until the current event loop pass is wrapping up is helpful. In order to allow microtasks to be used by third-party libraries, frameworks, and polyfills, the {{domxref("queueMicrotask()")}} method is exposed on the {{domxref("Window")}} and {{domxref("Worker")}} interfaces.
JavaScript [promises](/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) and the [Mutation Observer API](/en-US/docs/Web/API/MutationObserver) both use the microtask queue to run their callbacks, but there are other times when the ability to defer work until the current event loop pass is wrapping up is helpful. In order to allow microtasks to be used by third-party libraries, frameworks, and polyfills, the {{domxref("Window.queueMicrotask()", "queueMicrotask()")}} method is exposed on the {{domxref("Window")}} and {{domxref("WorkerGlobalScope")}} interfaces.

## Tasks vs. microtasks

Expand All @@ -36,7 +36,7 @@ There are two key differences.

First, each time a task exits, the event loop checks to see if the task is returning control to other JavaScript code. If not, it runs all of the microtasks in the microtask queue. The microtask queue is, then, processed multiple times per iteration of the event loop, including after handling events and other callbacks.

Second, if a microtask adds more microtasks to the queue by calling {{domxref("queueMicrotask()")}}, those newly-added microtasks _execute before the next task is run_. That's because the event loop will keep calling microtasks until there are none left in the queue, even if more keep getting added.
Second, if a microtask adds more microtasks to the queue by calling {{domxref("Window.queueMicrotask()", "queueMicrotask()")}}, those newly-added microtasks _execute before the next task is run_. That's because the event loop will keep calling microtasks until there are none left in the queue, even if more keep getting added.

> [!WARNING]
> Since microtasks can themselves enqueue more microtasks, and the event loop continues processing microtasks until the queue is empty, there's a real risk of getting the event loop endlessly processing microtasks. Be cautious with how you go about recursively adding microtasks.
Expand All @@ -47,7 +47,7 @@ Before getting farther into this, it's important to note again that most develop

### Enqueueing microtasks

As such, you should typically use microtasks only when there's no other solution, or when creating frameworks or libraries that need to use microtasks in order to create the functionality they're implementing. While there have been tricks available that made it possible to enqueue microtasks in the past (such as by creating a promise that resolves immediately), the addition of the {{domxref("queueMicrotask()")}} method adds a standard way to introduce a microtask safely and without tricks.
As such, you should typically use microtasks only when there's no other solution, or when creating frameworks or libraries that need to use microtasks in order to create the functionality they're implementing. While there have been tricks available that made it possible to enqueue microtasks in the past (such as by creating a promise that resolves immediately), the addition of the {{domxref("Window.queueMicrotask()", "queueMicrotask()")}} method adds a standard way to introduce a microtask safely and without tricks.

By introducing `queueMicrotask()`, the quirks that arise when sneaking in using promises to create microtasks can be avoided. For instance, when using promises to create microtasks, exceptions thrown by the callback are reported as rejected promises rather than being reported as standard exceptions. Also, creating and destroying promises takes additional overhead both in terms of time and memory that a function which properly enqueues microtasks avoids.

Expand Down Expand Up @@ -191,7 +191,7 @@ const logElem = document.getElementById("log");
const log = (s) => (logElem.innerText += `${s}\n`);
```

In the following code, we see a call to {{domxref("queueMicrotask()")}} used to schedule a microtask to run. This call is bracketed by calls to `log()`, a custom function that outputs text to the screen.
In the following code, we see a call to {{domxref("Window.queueMicrotask()", "queueMicrotask()")}} used to schedule a microtask to run. This call is bracketed by calls to `log()`, a custom function that outputs text to the screen.

```js
log("Before enqueueing the microtask");
Expand Down Expand Up @@ -220,7 +220,7 @@ const logElem = document.getElementById("log");
const log = (s) => (logElem.innerText += `${s}\n`);
```

In the following code, we see a call to {{domxref("queueMicrotask()")}} used to schedule a microtask to run. This call is bracketed by calls to `log()`, a custom function that outputs text to the screen.
In the following code, we see a call to {{domxref("Window.queueMicrotask()", "queueMicrotask()")}} used to schedule a microtask to run. This call is bracketed by calls to `log()`, a custom function that outputs text to the screen.

The code below schedules a timeout to occur in zero milliseconds, then enqueues a microtask. This is bracketed by calls to `log()` to output additional messages.

Expand Down Expand Up @@ -287,7 +287,7 @@ log("Main program exiting");
## See also

- [In depth: Microtasks and the JavaScript runtime environment](/en-US/docs/Web/API/HTML_DOM_API/Microtask_guide/In_depth)
- {{domxref("queueMicrotask()")}}
- {{domxref("Window.queueMicrotask()", "queueMicrotask()")}}
- [Asynchronous JavaScript](/en-US/docs/Learn/JavaScript/Asynchronous)
- [Introducing asynchronous JavaScript](/en-US/docs/Learn/JavaScript/Asynchronous/Introducing)
- [Cooperative asynchronous JavaScript: Timeouts and intervals](/en-US/docs/Learn/JavaScript/Asynchronous)
Expand Down
5 changes: 3 additions & 2 deletions files/en-us/web/api/settimeout/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -464,5 +464,6 @@ See also the [`clearTimeout()` example](/en-US/docs/Web/API/clearTimeout#example
- [Polyfill of `setTimeout` which allows passing arguments to the callback in `core-js`](https://github.com/zloirock/core-js#settimeout-and-setinterval)
- {{domxref("clearTimeout")}}
- {{domxref("setInterval()")}}
- {{domxref("window.requestAnimationFrame")}}
- {{domxref("queueMicrotask()")}}
- {{domxref("Window.requestAnimationFrame")}}
- {{domxref("Window.queueMicrotask()")}}
- {{domxref("WorkerGlobalScope.queueMicrotask()")}}
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ Some of the functions (a subset) that are common to all workers and to the main
- {{domxref("clearTimeout()")}}
- {{domxref("createImageBitmap()")}}
- {{domxref("WorkerGlobalScope.dump()", "dump()")}} {{non-standard_inline}}
- {{domxref("WorkerGlobalScope/fetch", "fetch()")}}
- {{domxref("queueMicrotask()")}}
- {{domxref("WorkerGlobalScope.fetch()", "fetch()")}}
- {{domxref("WorkerGlobalScope.queueMicrotask()", "queueMicrotask()")}}
- {{domxref("reportError()")}}
- {{domxref("setInterval()")}}
- {{domxref("setTimeout()")}}
Expand Down
4 changes: 2 additions & 2 deletions files/en-us/web/api/web_workers_api/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@ Some of the functions (a subset) that are common to all workers and to the main
- {{domxref("clearTimeout()")}}
- {{domxref("createImageBitmap()")}}
- {{domxref("WorkerGlobalScope.dump()", "dump()")}} {{non-standard_inline}}
- {{domxref("WorkerGlobalScope/fetch", "fetch()")}}
- {{domxref("queueMicrotask()")}}
- {{domxref("WorkerGlobalScope.fetch()", "fetch()")}}
- {{domxref("WorkerGlobalScope.queueMicrotask()", "queueMicrotask()")}}
- {{domxref("reportError()")}}
- {{domxref("setInterval()")}}
- {{domxref("setTimeout()")}}
Expand Down
2 changes: 1 addition & 1 deletion files/en-us/web/api/window/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ _This interface inherits methods from the {{domxref("EventTarget")}} interface._
- : Returns the text entered by the user in a prompt dialog.
- {{DOMxRef("Window.queryLocalFonts()")}} {{Experimental_Inline}} {{SecureContext_Inline}}
- : Returns a {{jsxref("Promise")}} that fulfills with an array of {{domxref("FontData")}} objects representing the font faces available locally.
- {{domxref("queueMicrotask", "Window.queueMicrotask()")}}
- {{domxref("Window.queueMicrotask()")}}
- : Queues a microtask to be executed at a safe time prior to control returning to the browser's event loop.
- {{domxref("reportError", "Window.reportError()")}}
- : Reports an error in a script, emulating an unhandled exception.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
---
title: queueMicrotask() global function
title: "Window: queueMicrotask() method"
short-title: queueMicrotask()
slug: Web/API/queueMicrotask
page-type: web-api-global-function
slug: Web/API/Window/queueMicrotask
page-type: web-api-instance-method
browser-compat: api.queueMicrotask
---

{{APIRef("HTML DOM")}}{{AvailableInWorkers}}
{{APIRef("HTML DOM")}}

The **`queueMicrotask()`** method,
which is exposed on the {{domxref("Window")}} or {{domxref("Worker")}} interface,
The **`queueMicrotask()`** method of the {{domxref("Window")}} interface
queues a microtask to be executed at a safe time prior to control returning to the
browser's event loop.

Expand All @@ -23,20 +22,20 @@ execution context, potentially depending on work you need to complete. You can l
more about how to use microtasks and why you might choose to do so in our [microtask guide](/en-US/docs/Web/API/HTML_DOM_API/Microtask_guide).

The importance of microtasks comes in its ability to perform tasks asynchronously but
in a specific order. See [Using microtasks in JavaScript with queueMicrotask()](/en-US/docs/Web/API/HTML_DOM_API/Microtask_guide) for more details.
in a specific order. See [Using microtasks in JavaScript with `queueMicrotask()`](/en-US/docs/Web/API/HTML_DOM_API/Microtask_guide) for more details.

Microtasks are especially useful for libraries and frameworks that need to perform
final cleanup or other just-before-rendering tasks.

## Syntax

```js-nolint
queueMicrotask(() => {/* ... */})
queueMicrotask(callback)
```

### Parameters

- `function`
- `callback`
- : A {{jsxref("function")}} to be executed when the browser engine determines it is
safe to call your code. Enqueued microtasks are executed after all pending tasks have
completed but before yielding control to the browser's event loop.
Expand Down Expand Up @@ -84,6 +83,7 @@ MyElement.prototype.loadData = function (url) {

## See also

- {{domxref("WorkerGlobalScope.queueMicrotask()")}}
- [Polyfill of `queueMicrotask()` in `core-js`](https://github.com/zloirock/core-js#queuemicrotask)
- [Using microtasks in JavaScript with queueMicrotask()](/en-US/docs/Web/API/HTML_DOM_API/Microtask_guide)
- [Asynchronous JavaScript](/en-US/docs/Learn/JavaScript/Asynchronous)
Expand Down
2 changes: 1 addition & 1 deletion files/en-us/web/api/workerglobalscope/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ _This interface inherits methods from the {{domxref("EventTarget")}} interface._
- : Starts the process of fetching a resource from the network.
- {{domxref("WorkerGlobalScope.importScripts()")}}
- : Imports one or more scripts into the worker's scope. You can specify as many as you'd like, separated by commas. For example: `importScripts('foo.js', 'bar.js');`.
- {{domxref("queueMicrotask()", "WorkerGlobalScope.queueMicrotask()")}}
- {{domxref("WorkerGlobalScope.queueMicrotask()")}}
- : Queues a microtask to be executed at a safe time prior to control returning to the browser's event loop.
- {{domxref("setInterval()", "WorkerGlobalScope.setInterval()")}}
- : Schedules a function to execute every time a given number of milliseconds elapses.
Expand Down
Loading