Skip to content

Commit

Permalink
zh-cn: resolve the global function queueMicrotask()
Browse files Browse the repository at this point in the history
  • Loading branch information
yin1999 authored and sora32127 committed Oct 6, 2024
1 parent 320af15 commit 8468cf2
Show file tree
Hide file tree
Showing 8 changed files with 111 additions and 31 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ greetUser("Veronica");
## 参见

- [微任务指南](/zh-CN/docs/Web/API/HTML_DOM_API/Microtask_guide)
- {{domxref("queueMicrotask()")}}
- {{domxref("Window.queueMicrotask()")}}
- [异步 JavaScript](/zh-CN/docs/Learn/JavaScript/Asynchronous)
- [异步 JavaScript 简介](/zh-CN/docs/Learn/JavaScript/Asynchronous/Introducing)
- [合作的异步 JavaScript:超时和间隔](/zh-CN/docs/Learn/JavaScript/Asynchronous)
Expand Down
18 changes: 8 additions & 10 deletions files/zh-cn/web/api/html_dom_api/microtask_guide/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ slug: Web/API/HTML_DOM_API/Microtask_guide

一个**微任务**(microtask)就是一个简短的函数,当创建该微任务的函数执行之后,*并且*只有当 Javascript 调用栈为空,而控制权尚未返还给被{{Glossary("user agent", "用户代理")}}用来驱动脚本执行环境的事件循环之前,该微任务才会被执行。事件循环既可能是浏览器的主事件循环也可能是被一个 [web worker](/zh-CN/docs/Web/API/Web_Workers_API) 所驱动的事件循环。这使得给定的函数在没有其他脚本执行干扰的情况下运行,也保证了微任务能在用户代理有机会对该微任务带来的行为做出反应之前运行。

JavaScript 中的 [promise](/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Promise)[Mutation Observer API](/zh-CN/docs/Web/API/MutationObserver) 都使用微任务队列去运行它们的回调函数,但当能够推迟工作直到当前事件循环过程完结时,也是可以执行微任务的时机。为了允许第三方库、框架、polyfill 能使用微任务,在 {{domxref("Window")}} 和 {{domxref("Worker")}} 接口上暴露了 {{domxref("queueMicrotask()")}} 方法。
JavaScript 中的 [promise](/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Promise)[Mutation Observer API](/zh-CN/docs/Web/API/MutationObserver) 都使用微任务队列去运行它们的回调函数,但当能够推迟工作直到当前事件循环过程完结时,也是可以执行微任务的时机。为了允许第三方库、框架、polyfill 能使用微任务,在 {{domxref("Window")}} 和 {{domxref("WorkerGlobalScope")}} 接口上暴露了 {{domxref("Window.queueMicrotask()", "queueMicrotask()")}} 方法。

## 任务 vs 微任务

Expand All @@ -33,7 +33,7 @@ JavaScript 中的 [promise](/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/

首先,每当一个任务存在,事件循环都会检查该任务是否正把控制权交给其他 JavaScript 代码。如若不然,事件循环就会运行微任务队列中的所有微任务。接下来微任务循环会在事件循环的每次迭代中被处理多次,包括处理完事件和其他回调之后。

其次,如果一个微任务通过调用 {{domxref("queueMicrotask()")}}, 向队列中加入了更多的微任务,则那些新加入的微任务 _会早于下一个任务运行_。这是因为事件循环会持续调用微任务直至队列中没有留存的,即使是在有更多微任务持续被加入的情况下。
其次,如果一个微任务通过调用 {{domxref("Window.queueMicrotask()", "queueMicrotask()")}},向队列中加入了更多的微任务,则那些新加入的微任务*会早于下一个任务运行*。这是因为事件循环会持续调用微任务直至队列中没有留存的,即使是在有更多微任务持续被加入的情况下。

> [!WARNING]
> 因为微任务自身可以入列更多的微任务,且事件循环会持续处理微任务直至队列为空,那么就存在一种使得事件循环无尽处理微任务的真实风险。如何处理递归增加微任务是要谨慎而行的。
Expand All @@ -44,11 +44,11 @@ JavaScript 中的 [promise](/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/

### 入列微任务

就其本身而言,应该使用微任务的典型情况,要么只有在没有其他办法的时候,要么是当创建框架或库时需要使用微任务达成其功能。虽然在过去要使得入列微任务成为可能有可用的技巧(比如创建一个立即 resolve 的 promise),但新加入的 {{domxref("queueMicrotask()")}} 方法增加了一种标准的方式,可以安全的引入微任务而避免使用额外的技巧。
就其本身而言,应该使用微任务的典型情况,要么只有在没有其他办法的时候,要么是当创建框架或库时需要使用微任务达成其功能。虽然在过去要使得入列微任务成为可能有可用的技巧(比如创建一个立即兑现的 promise),但新加入的 {{domxref("Window.queueMicrotask()", "queueMicrotask()")}} 方法增加了一种标准的方式,可以安全的引入微任务而避免使用额外的技巧。

通过引入 `queueMicrotask()`,由晦涩地使用 promise 去创建微任务而带来的风险就可以被避免了。举例来说,当使用 promise 创建微任务时,由回调抛出的异常被报告为 rejected promises 而不是标准异常。同时,创建和销毁 promise 带来了事件和内存方面的额外开销,这是正确入列微任务的函数应该避免的。

简单的传入一个 JavaScript {{jsxref("Function")}} ,以在 `queueMicrotask()` 方法中处理微任务时供其上下文调用即可;取决于当前执行上下文, `queueMicrotask()` 以定义的形式被暴露在 {{domxref("Window")}} 或 {{domxref("Worker")}} 接口上。
简单的传入一个 JavaScript {{jsxref("Function")}},以在 `queueMicrotask()` 方法中处理微任务时供其上下文调用即可;取决于当前执行上下文,`queueMicrotask()` 以定义的形式被暴露在 {{domxref("Window")}} 或 {{domxref("Worker")}} 接口上。

```js
queueMicrotask(() => {
Expand Down Expand Up @@ -175,9 +175,7 @@ let sendMessage = (message) => {
};
```
`sendMessage()`
被调用时,指定的消息首先被推入消息队列数组。接着事情就变得有趣了。
`sendMessage()` 被调用时,指定的消息首先被推入消息队列数组。接着事情就变得有趣了。
如果我们刚加入数组的消息是第一条,就入列一个将会发送一个批处理的微任务。照旧,当 JavaScript 执行路径到达顶层,恰在运行回调之前,那个微任务将会执行。这意味着之后的间歇期内造成的对 `sendMessage()` 的任何调用都会将其各自的消息推入消息队列,但囿于入列微任务逻辑之前的数组长度检查,不会有新的微任务入列。
Expand All @@ -204,7 +202,7 @@ let logElem = document.getElementById("log");
let log = (s) => (logElem.innerHTML += s + "<br>");
```
在下面的代码中,我们看到对 {{domxref("queueMicrotask()")}} 的一次调用被用来调度一个微任务以使其运行。这次调用包含了 `log()`,一个简单的向屏幕输出文字的自定义函数。
在下面的代码中,我们看到对 {{domxref("Window.queueMicrotask()", "queueMicrotask()")}} 的一次调用被用来调度一个微任务以使其运行。这次调用包含了 `log()`,一个简单的向屏幕输出文字的自定义函数。
```js
log("Before enqueueing the microtask");
Expand Down Expand Up @@ -233,7 +231,7 @@ let logElem = document.getElementById("log");
let log = (s) => (logElem.innerHTML += s + "<br>");
```
在下面的代码中,我们看到对 {{domxref("queueMicrotask()")}} 的一次调用被用来调度一个微任务以使其运行。这次调用包含了 `log()`,一个简单的向屏幕输出文字的自定义函数。
在下面的代码中,我们看到对 {{domxref("Window.queueMicrotask()", "queueMicrotask()")}} 的一次调用被用来调度一个微任务以使其运行。这次调用包含了 `log()`,一个简单的向屏幕输出文字的自定义函数。
以下代码调度了一个 0 毫秒后触发的 timeout,而后入列了一个微任务。前后被对 `log()` 的调用包住,输出附加的信息。
Expand Down Expand Up @@ -300,7 +298,7 @@ log("Main program exiting");
## 参见
- [In depth: Microtasks and the JavaScript runtime environment](/zh-CN/docs/Web/API/HTML_DOM_API/Microtask_guide/In_depth)
- {{domxref("queueMicrotask()")}}
- {{domxref("Window.queueMicrotask()", "queueMicrotask()")}}
- [Asynchronous JavaScript](/zh-CN/docs/Learn/JavaScript/Asynchronous)
- [General asynchronous programming concepts](/zh-CN/docs/Learn/JavaScript/Asynchronous/Concepts)
Expand Down
5 changes: 3 additions & 2 deletions files/zh-cn/web/api/settimeout/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -385,5 +385,6 @@ function clearMessage() {
- [`core-js` 中允许向回调函数传递参数的 `setTimeout` 版本的 polyfill](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 @@ -23,8 +23,8 @@ slug: Web/API/Web_Workers_API/Functions_and_classes_available_to_workers
- {{domxref("clearTimeout()")}}
- {{domxref("createImageBitmap()")}}
- {{domxref("WorkerGlobalScope.dump()", "dump()")}} {{non-standard_inline}}
- {{domxref("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/zh-cn/web/api/web_workers_api/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ worker 在一个与当前 {{DOMxRef("window")}} 不同的全局上下文中运
- {{domxref("clearTimeout()")}}
- {{domxref("createImageBitmap()")}}
- {{domxref("WorkerGlobalScope.dump()", "dump()")}} {{non-standard_inline}}
- {{domxref("fetch()")}}
- {{domxref("queueMicrotask()")}}
- {{domxref("WorkerGlobalScope.fetch()", "fetch()")}}
- {{domxref("WorkerGlobalScope.queueMicrotask()", "queueMicrotask()")}}
- {{domxref("reportError()")}}
- {{domxref("setInterval()")}}
- {{domxref("setTimeout()")}}
Expand Down
28 changes: 15 additions & 13 deletions files/zh-cn/web/api/window/queuemicrotask/index.md
Original file line number Diff line number Diff line change
@@ -1,31 +1,32 @@
---
title: queueMicrotask()
title: Window:queueMicrotask() 方法
slug: Web/API/Window/queueMicrotask
original_slug: Web/API/queueMicrotask
l10n:
sourceCommit: 5fc275a2cb01ea3c361d6a0af057e96a00122984
---

{{APIRef("HTML DOM")}}

{{domxref("Window")}} 或 {{domxref("Worker")}} 接口的 **`queueMicrotask()`** 方法,将微任务加入队列以在控制返回浏览器的事件循环之前的安全时间执行。
{{domxref("Window")}} 接口的 **`queueMicrotask()`** 方法,将微任务加入队列以在控制返回浏览器的事件循环之前的安全时间执行。

微任务是一个简短的函数,它将在当前任务完成其工作后运行,并且在执行上下文的控制权返回到浏览器的事件循环之前没有其他代码等待运行时运行。

它让你的代码在运行时不会干扰任何可能具有更高优先级的代码的运行,但在浏览器重新获得对执行上下文的控制之前,这可能取决于你需要完成的工作。你可以在我们的[微任务指南](/zh-CN/docs/Web/API/HTML_DOM_API/Microtask_guide)中了解更多关于如何使用微任务以及选择这样做的原因。

微任务的重要性在于它能够以特定顺序异步执行任务。查看[在 JavaScript 中通过 queueMicrotask() 使用微任务](/zh-CN/docs/Web/API/HTML_DOM_API/Microtask_guide)的详情
微任务的重要性在于它能够以特定顺序异步执行任务。参见[在 JavaScript 中通过 `queueMicrotask()` 使用微任务](/zh-CN/docs/Web/API/HTML_DOM_API/Microtask_guide)以了解更多信息

微任务对于需要执行最后阶段的任务或其他在渲染之前的任务的库和框架特别有用。

## 语法

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

### 参数

- `function`
- : 当浏览器引擎确定可以安全调用你的代码时执行的 {{jsxref("function")}}。微任务(microtask)的执行顺序在所有进行中的任务(pending task)完成之后,在对浏览器的事件循环产生控制(yielding control to the browser's event loop)之前
- : 当浏览器引擎确定可以安全调用你的代码时执行的 {{jsxref("function")}}。微任务(microtask)的执行顺序在所有进行中的任务(pending task)完成之后,在对浏览器的事件循环产生控制之前

### 返回值

Expand All @@ -39,7 +40,7 @@ queueMicrotask(() => {
});
```

来自 [`queueMicrotask` 的规范文档:](https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html#microtask-queuing)
来自 [queueMicrotask 的规范](https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html#microtask-queuing)

```js
MyElement.prototype.loadData = function (url) {
Expand Down Expand Up @@ -70,8 +71,9 @@ MyElement.prototype.loadData = function (url) {

## 参见

- [Polyfill of `queueMicrotask()` in `core-js`](https://github.com/zloirock/core-js#queuemicrotask)
- [Using microtasks in JavaScript with queueMicrotask()](/zh-CN/docs/Web/API/HTML_DOM_API/Microtask_guide)
- [Asynchronous JavaScript](/zh-CN/docs/Learn/JavaScript/Asynchronous)
- [queueMicrotask explainer](https://github.com/fergald/docs/blob/master/explainers/queueMicrotask.md)
- [Tasks, microtasks, queues and schedules](https://jakearchibald.com/2015/tasks-microtasks-queues-and-schedules/) by Jake Archibald
- {{domxref("WorkerGlobalScope.queueMicrotask()")}}
- [`core-js``queueMicrotask()` 的 polyfill](https://github.com/zloirock/core-js#queuemicrotask)
- [在 JavaScript 中通过 queueMicrotask() 使用微任务](/zh-CN/docs/Web/API/HTML_DOM_API/Microtask_guide)
- [异步 JavaScript](/zh-CN/docs/Learn/JavaScript/Asynchronous)
- [queueMicrotask 的解释](https://github.com/fergald/docs/blob/master/explainers/queueMicrotask.md)
- [任务、微任务、队列和调度](https://jakearchibald.com/2015/tasks-microtasks-queues-and-schedules/)(作者:Jake Archibald)
79 changes: 79 additions & 0 deletions files/zh-cn/web/api/workerglobalscope/queuemicrotask/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
---
title: WorkerGlobalScope:queueMicrotask() 方法
slug: Web/API/WorkerGlobalScope/queueMicrotask
l10n:
sourceCommit: 5fc275a2cb01ea3c361d6a0af057e96a00122984
---

{{APIRef("Web Workers API")}}{{AvailableInWorkers("worker")}}

{{domxref("WorkerGlobalScope")}} 接口的 **`queueMicrotask()`** 方法,将微任务加入队列以在控制返回浏览器的事件循环之前的安全时间执行。

微任务是一个简短的函数,它将在当前任务完成其工作后运行,并且在执行上下文的控制权返回到浏览器的事件循环之前没有其他代码等待运行时运行。

它让你的代码在运行时不会干扰任何可能具有更高优先级的代码的运行,但在浏览器重新获得对执行上下文的控制之前,这可能取决于你需要完成的工作。你可以在我们的[微任务指南](/zh-CN/docs/Web/API/HTML_DOM_API/Microtask_guide)中了解更多关于如何使用微任务以及选择这样做的原因。

微任务的重要性在于它能够以特定顺序异步执行任务。参见[在 JavaScript 中通过 `queueMicrotask()` 使用微任务](/zh-CN/docs/Web/API/HTML_DOM_API/Microtask_guide)以了解更多信息。

微任务对于需要执行最后阶段的任务或其他在渲染之前的任务的库和框架特别有用。

## 语法

```js-nolint
queueMicrotask(callback)
```

### 参数

- `function`
- : 当浏览器引擎确定可以安全调用你的代码时执行的 {{jsxref("function")}}。微任务(microtask)的执行顺序在所有进行中的任务(pending task)完成之后,在对浏览器的事件循环产生控制之前。

### 返回值

无({{jsxref("undefined")}})。

## 示例

```js
queueMicrotask(() => {
// 函数的内容
});
```

来自 [queueMicrotask 的规范](https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html#microtask-queuing)

```js
MyElement.prototype.loadData = function (url) {
if (this._cache[url]) {
queueMicrotask(() => {
this._setData(this._cache[url]);
this.dispatchEvent(new Event("load"));
});
} else {
fetch(url)
.then((res) => res.arrayBuffer())
.then((data) => {
this._cache[url] = data;
this._setData(data);
this.dispatchEvent(new Event("load"));
});
}
};
```

## 规范

{{Specifications}}

## 浏览器兼容性

{{Compat}}

## 参见

- {{domxref("Window.queueMicrotask()")}}
- [`core-js``queueMicrotask()` 的 polyfill](https://github.com/zloirock/core-js#queuemicrotask)
- [在 JavaScript 中通过 queueMicrotask() 使用微任务](/zh-CN/docs/Web/API/HTML_DOM_API/Microtask_guide)
- [异步 JavaScript](/zh-CN/docs/Learn/JavaScript/Asynchronous)
- [queueMicrotask 的解释](https://github.com/fergald/docs/blob/master/explainers/queueMicrotask.md)
- [任务、微任务、队列和调度](https://jakearchibald.com/2015/tasks-microtasks-queues-and-schedules/)(作者:Jake Archibald)
2 changes: 1 addition & 1 deletion files/zh-cn/web/javascript/guide/using_promises/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -542,7 +542,7 @@ Promise 回调(.then)

你可能遇到如下情况:你的一些 Promise 和任务(例如事件或回调)会以不可预测的顺序启动。此时,你或许可以通过使用微任务检查状态或平衡 Promise,并以此有条件地创建 Promise。

如果你认为微任务可能会帮助你解决问题,那么请阅读[微任务指南](/zh-CN/docs/Web/API/HTML_DOM_API/Microtask_guide),学习如何用 [`queueMicrotask()`](/zh-CN/docs/Web/API/queueMicrotask) 来将一个函数作为微任务添加到队列中。
如果你认为微任务可能会帮助你解决问题,那么请阅读[微任务指南](/zh-CN/docs/Web/API/HTML_DOM_API/Microtask_guide),学习如何用 {{domxref("Window.queueMicrotask()", "queueMicrotask()")}} 来将一个函数作为微任务添加到队列中。

## 参见

Expand Down

0 comments on commit 8468cf2

Please sign in to comment.