在哪做网站关键词,wordpress后台js加载时间过长,网站建设域名跳转博客,wordpress 文章分类页Web Workers API
1、指南
1.1 使用Web Workers
Web Workers是一种让Web内容在后台线程中运行脚本的简单方法。工作线程可以在不干扰用户界面的情况下执行任务。此外#xff0c;它们还可以使用XMLHttpRequest(尽管responseXML和channel属性总是为空)或fetch(没有此类限制)执…Web Workers API
1、指南
1.1 使用Web Workers
Web Workers是一种让Web内容在后台线程中运行脚本的简单方法。工作线程可以在不干扰用户界面的情况下执行任务。此外它们还可以使用XMLHttpRequest(尽管responseXML和channel属性总是为空)或fetch(没有此类限制)执行I/O。工作线程一旦被创建就可以通过向JavaScript代码指定的事件处理程序发送消息来向创建它的JavaScript代码发送消息(反之亦然)。
本文详细介绍了如何使用web worker。
1.1.1 Dedicated workers
如上所述Dedicated worker只能由调用它的脚本访问。在本节中我们将讨论在 Basic dedicated worker example示例中发现的JavaScript:它允许您输入两个要相乘的数字。这些数字被发送给一个专门的工作者相乘结果返回到页面并显示。
这个示例相当简单但我们决定在向您介绍基本的worker概念时保持简单。本文稍后将介绍更高级的细节。
Worker feature detection
为了更好地控制错误处理和向后兼容性将 worker 访问代码包装在下面(main.js)中是一个好主意:
if (window.Worker) {// …
}Spawning a dedicated worker
创建一个新的worker很简单。您所需要做的就是调用Worker()构造函数指定要在Worker线程中执行的脚本的URI。
// main.js
const myWorker new Worker(worker.js);向专用worker发送和从专用worker发送消息
worker的魔力是通过postMessage()方法和onmessage事件处理程序实现的。当您想要向worker发送消息时您可以像这样向它发送消息
first.onchange () {myWorker.postMessage([first.value, second.value]);console.log(Message posted to worker);
};second.onchange () {myWorker.postMessage([first.value, second.value]);console.log(Message posted to worker);
};这里有两个input元素分别由变量first和second表示;当其中一个的值被改变时myWorker.postMessage([first.value,second.value])被用来将两者中的值以数组的形式发送给worker。你可以在消息中发送任何你喜欢的东西。
在worker中当收到消息时我们可以通过编写这样的事件处理程序块来响应:
// worker.js
onmessage (e) {console.log(Message received from main script);const workerResult Result: ${e.data[0] * e.data[1]};console.log(Posting message back to main script);postMessage(workerResult);
};onmessage处理程序允许我们在接收到消息时运行一些代码消息本身在message 事件的data属性中可用。这里我们将两个数字相乘然后再次使用postMessage()将结果发送回主线程。
回到主线程我们再次使用onmessage来响应从worker发送回来的消息:
myWorker.onmessage (e) {result.textContent e.data;console.log(Message received from worker);
};这里我们获取消息事件数据并将其设置为result段落的textContent这样用户就可以看到计算的结果。
结束 worker
如果你需要在主线程中立即终止一个正在运行的worker你可以通过调用worker的terminate方法来完成:
myWorker.terminate();工作线程被立即终止。
处理错误
当工作线程中发生运行时错误时将调用其onerror事件处理程序。它接收一个名为error的事件该事件实现了ErrorEvent接口。
事件不会冒泡并且可以取消;为了防止默认操作发生worker可以调用错误事件的preventDefault()方法。
错误事件有以下三个感兴趣的字段:
message 一个人类可读的错误信息。filename 发生错误的脚本文件的名称。lineno 发生错误的脚本文件的行号。
Spawning subworkers
如果workers 愿意他们可能会产生更多的workers 。所谓的子worker必须托管在与父页面相同的源中。此外子worker的uri是相对于父worker的位置而不是所属页面的位置进行解析的。这使得workers 更容易跟踪他们的依赖项在哪里。
导入脚本和库
工作线程可以访问全局函数importScripts()该函数允许它们导入脚本。它接受零个或多个uri作为要导入的资源的参数;以下所有例子都是正确的:
importScripts(); /* imports nothing */
importScripts(foo.js); /* imports just foo.js */
importScripts(foo.js, bar.js); /* imports two scripts */
importScripts(//example.com/hello.js,
); /* You can import scripts from other origins */浏览器加载列出的每个脚本并执行它。然后worker可以使用每个脚本中的任何全局对象。如果无法加载脚本则抛出NETWORK_ERROR并且不会执行后续代码。之前执行的代码(包括使用setTimeout()延迟的代码)仍然可以使用。还保留了importScripts()方法之后的函数声明因为它们总是在其余代码之前求值。
1.1.2 Shared workers
一个共享的工作线程可以被多个脚本访问——即使它们被不同的窗口、iframe甚至工作线程访问。在本节中我们将讨论基 Basic shared worker example示例中的JavaScript(运行shared worker):这与basic dedicated worker 示例非常相似除了它有两个可用的函数由不同的脚本文件处理:两个数字的乘法或一个数字的平方。两个脚本都使用同一个worker来执行所需的实际计算。
在这里我们将集中讨论 dedicated workers 和shared workers之间的区别。请注意在这个示例中我们有两个HTML页面每个页面都应用了使用相同工作文件的JavaScript。
生成一个 shared worker
生成一个新的共享工作线程与 dedicated 工作线程非常相似但使用不同的构造函数名称(参见index.html和index2.html) -每个构造函数都必须使用如下代码启动工作线程:
const myWorker new SharedWorker(worker.js);一个很大的区别是对于共享工作线程您必须通过port 对象进行通信—打开一个显式端口脚本可以使用该端口与工作线程进行通信(这在 dedicated 工作线程的情况下隐式完成)。
端口连接需要通过使用onmessage事件处理程序隐式启动或者在发布任何消息之前显式地使用start()方法启动。只有当消息事件通过addEventListener()方法连接时才需要调用start()。 注意:当使用start()方法打开端口连接时如果需要双向通信则需要从父线程和工作线程都调用该方法。 向共享worker发送消息和从共享worker发送消息
现在消息可以像以前一样发送到worker但是postMessage()方法必须通过port对象调用(同样你会在 multiply.js和square.js中看到类似的结构):
// square.js/multiply.js
squareNumber.onchange () {myWorker.port.postMessage([squareNumber.value, squareNumber.value]);console.log(Message posted to worker);
};现在来看看worker。这里也有一点复杂
onconnect (e) {const port e.ports[0];port.onmessage (e) {const workerResult Result: ${e.data[0] * e.data[1]};port.postMessage(workerResult);};
};首先当端口连接发生时我们使用onconnect处理程序来触发代码(例如当父线程中的onmessage事件处理程序被设置时或者当父线程中显式调用start()方法时)。
我们使用该事件对象的ports属性来获取端口并将其存储在一个变量中。
接下来我们在端口上添加一个onmessage处理程序来执行计算并将结果返回给主线程。在工作线程中设置这个onmessage处理程序也会隐式地打开到父线程的端口连接因此实际上不需要调用port.start()如上所述。
最后回到主脚本我们处理消息(同样您将在multi .js和square.js中看到类似的结构)。
// multiply.js and square.js
myWorker.port.onmessage (e) {result2.textContent e.data;console.log(Message received from worker);
};当消息通过端口从worker返回时我们将计算结果插入到适当的结果段落中。
1.2 Web worker可用的函数和类
除了标准的JavaScript函数集(如String、Array、Object、JSON等)之外还有各种各样的函数可以从DOM中提供给worker。本文提供了一个列表。
Worker Contexts Functions
工作线程运行在与当前窗口window不同的全局上下文中!虽然Window不是直接对worker可用但许多相同的方法都是在一个共享的mixin (WindowOrWorkerGlobalScope)中定义的并且通过worker自己的WorkerGlobalScope派生的上下文提供给worker使用:
DedicatedWorkerGlobalScope for dedicated workersSharedWorkerGlobalScope for shared workersServiceWorkerGlobalScope for service workers
一些函数(一个子集)是所有工作线程和主线程(来自WindowOrWorkerGlobalScope)共同的:
atob()btoa()clearInterval()clearTimeout()dump() Non-standardqueueMicrotask()setInterval()setTimeout()structuredClone()window.requestAnimationFrame (dedicated workers only)window.cancelAnimationFrame (dedicated workers only)
以下函数仅对worker可用:
WorkerGlobalScope.importScripts() (all workers)DedicatedWorkerGlobalScope.postMessage (dedicated workers only)
worker中可用的Web APIs 注意:如果列出的API在特定版本中被平台支持那么通常可以认为它在web worker中可用。您还可以使用网站https://worker-playground.glitch.me/测试对特定对象/函数的支持 1.3 结构化克隆算法
结构化克隆算法复制复杂的JavaScript对象。它在调用structuredClone()时内部使用通过postMessage()在 worker 之间传输数据使用IndexedDB存储对象或为其他api复制对象。
它通过递归遍历输入对象进行克隆同时维护以前访问过的引用的映射以避免无限遍历循环。
结构化克隆不适用的东西
函数对象不能被结构化克隆算法复制;试图抛出DataCloneError异常。克隆 DOM 节点同样会抛出DataCloneError异常。某些对象属性不保留: 不保留RegExp对象的lastIndex属性。属性描述符、setter、getter和类似元数据的特性不复制。例如如果一个对象用属性描述符标记为只读那么它将在副本中被读/写因为这是默认的。原型链prototype chain不会被遍历或复制。
支持的类型
JavaScript types
Error types
Web/API types
1.4 Transferable objects
可转移对象Transferable objects是拥有资源的对象这些资源可以从一个上下文中转移到另一个上下文中从而确保资源一次只在一个上下文中可用。转移后原对象不再可用;它不再指向传输的资源并且任何读取或写入该对象的尝试都会抛出异常。
可转移对象通常用于共享一次只能安全地暴露给单个JavaScript线程的资源。例如ArrayBuffer是一个可转移的对象它拥有一块内存。当这样的缓冲区在线程之间传输时相关的内存资源将从原始缓冲区中分离出来并附加到新线程中创建的缓冲区对象上。原始线程中的缓冲区对象不再可用因为它不再拥有内存资源。
在使用structuredClone()创建对象的深度拷贝时也可能使用Transferring 。克隆操作之后转移的资源将被移动而不是复制到克隆对象中。
用于传输对象资源的机制取决于对象本身。例如当在线程之间传输ArrayBuffer时它所指向的内存资源实际上是在上下文之间以快速有效的零复制操作移动的。其他对象可以通过复制相关资源然后从旧上下文中删除来传输。
并不是所有的对象都是可转移的。下面提供了可转移对象的列表。
在线程之间传输对象
下面的代码演示了将消息从主线程发送到web worker线程时传输是如何工作的。Uint8Array在工作中被复制(复制)而它的缓冲区被转移。传输后从主线程读取或写入uInt8Array的任何尝试都会抛出但您仍然可以检查byteLength以确认它现在为零。
// Create an 8MB file and fill it. 8MB 1024 * 1024 * 8 B
const uInt8Array new Uint8Array(1024 * 1024 * 8).map((v, i) i);
console.log(uInt8Array.byteLength); // 8388608// Transfer the underlying buffer to a worker
worker.postMessage(uInt8Array, [uInt8Array.buffer]);
console.log(uInt8Array.byteLength); // 0注意:类型化数组如Int32Array和Uint8Array是可序列化的但不可转移。然而它们的底层缓冲区是ArrayBuffer这是一个可转移的对象。我们可以在data参数发送uInt8Array.buffer。而不是传输数组中的uInt8Array。 克隆操作期间的转移
下面的代码显示了structuredClone()操作其中底层缓冲区从原始对象复制到克隆对象。
const original new Uint8Array(1024);
const clone structuredClone(original);
console.log(original.byteLength); // 1024
console.log(clone.byteLength); // 1024original[0] 1;
console.log(clone[0]); // 0// Transferring the Uint8Array would throw an exception as it is not a transferable object
// const transferred structuredClone(original, {transfer: [original]});// We can transfer Uint8Array.buffer.
const transferred structuredClone(original, { transfer: [original.buffer] });
console.log(transferred.byteLength); // 1024
console.log(transferred[0]); // 1// After transferring Uint8Array.buffer cannot be used.
console.log(original.byteLength); // 0Supported objects 注意:可转移对象在Web IDL文件中被标记为属性[Transferable]。 2、接口
2.1 DedicatedWorkerGlobalScope
可以通过self关键字访问DedicatedWorkerGlobalScope对象(Worker全局作用域)。JavaScript Reference中列出了一些额外的全局函数、命名空间对象和构造函数它们通常不与worker全局作用域关联但在它上可用。参见:Functions available to workers.。
2.2 ServiceWorker
2.3 SharedWorker
2.4 SharedWorkerGlobalScope
2.5 Worker
Web Workers API 的Worker接口代表了一个可以通过脚本创建的后台任务它可以将消息发送回它的创建者。
通过调用Worker(path/to/worker/script)构造函数来创建 worker。
Workers 可以自己产生新的Workers 只要这些Workers 被托管在与父页相同的origin。
并不是所有的接口和函数都对 Worker中 的脚本可用。Workers 可以使用XMLHttpRequest进行网络通信但是它的responseXML和channel属性总是为null。(fetch也是可用的没有这样的限制。) 构造函数
Worker()
创建一个专用dedicated的web worker执行指定的URL处的脚本。这也适用于 Blob URLs。该脚本必须遵守同源策略。 注意:浏览器制造商对于数据URL是否同源存在分歧。虽然Firefox 10及以后的版本接受数据url但并非所有其他浏览器都是如此。 new Worker(aURL)
new Worker(aURL, options)aURL 一个字符串表示工作线程将要执行的脚本的URL。它必须遵守同源策略。 options 可选 一个对象其中包含可在创建对象实例时设置的选项属性。可用的属性如下: type 指定要创建的工作线程类型的字符串。取值为classic或module。如果未指定则使用的默认值为classic。 credentials 指定工作线程使用的凭据类型的字符串。该值可以是omit、same-origin或include。如果没有指定或者如果type是classic则默认使用omit (不需要凭据)。 name 一个字符串指定用于表示工作器范围的DedicatedWorkerGlobalScope的标识名主要用于调试目的。
实例方法
Worker.postMessage() 发送一个消息——由任何JavaScript对象组成——到worker的内部作用域。
Worker postMessage()方法委托给MessagePort postMessage()方法该方法在事件循环中添加一个与接收MessagePort相对应的任务。
Worker可以使用DedicatedWorkerGlobalScope.postMessage方法将信息发送回生成它的线程。
postMessage(message)
postMessage(message, options)
postMessage(message, transfer)message 交付给worker的对象;这将在交付给DedicatedWorkerGlobalScope.message_event 事件的data 字段中。这可以是由结构化克隆算法处理的任何值或JavaScript对象其中包括循环引用。 如果没有提供消息参数解析器将抛出SyntaxError。如果要传递给worker的数据不重要则可以显式传递null或undefined。 options 可选 一个可选对象它包含一个transfer 字段该字段包含一组要传输其所有权的可传输对象。如果对象的所有权被转移它将在发送它的上下文中变得不可用并且只对发送它的 worker 可用。 transfer 可选 可转移对象的可选数组用于转移其所有权。如果对象的所有权被转移它将在发送它的上下文中变得不可用并且只对发送它的worker 可用。 可转移对象是类的实例如ArrayBuffer, MessagePort或ImageBitmap对象可以被转移。null不是可接受的transfer值。 注意: postMessage()一次只能发送一个对象。如上所示如果你想传递多个值你可以发送一个数组。 Worker.terminate() 立即终止 worker。这不会让worker完成它的操作;它立刻停止了。ServiceWorker实例不支持此方法。
事件 error 在工作线程中发生错误时触发。 message 当worker的父进程收到来自该worker的消息时触发。 messageerror 当Worker对象接收到无法反序列化的消息时触发。 rejectionhandled 每次Promise被拒绝时触发不管是否有处理程序来捕获拒绝。 unhandledrejection 当Promise拒绝而没有处理程序捕获拒绝时触发。
Example
下面的代码片段使用Worker()构造函数创建一个Worker对象然后使用该Worker对象:
const myWorker new Worker(/worker.js);
const first document.querySelector(input#number1);
const second document.querySelector(input#number2);first.onchange () {myWorker.postMessage([first.value, second.value]);console.log(Message posted to worker);
};有关完整示例请参阅我们的 Basic dedicated worker example
2.6 WorkerGlobalScope
Web Workers API的WorkerGlobalScope接口是一个表示任何worker的作用域的接口。Workers 没有浏览器上下文;这个范围包含通常由Window对象传递的信息——在本例中是事件处理程序、控制台或相关的WorkerNavigator对象。每个WorkerGlobalScope都有自己的事件循环。
这个接口通常被每个worker类型特例化:dedicated worker的专用 DedicatedWorkerGlobalScope , shared worker的共享SharedWorkerGlobalScope, ServiceWorker的ServiceWorkerGlobalScope。self属性返回每个上下文的专用范围。 Example
你不能在代码中直接访问WorkerGlobalScope;然而它的属性和方法是由更具体的全局作用域继承的比如DedicatedWorkerGlobalScope和SharedWorkerGlobalScope。例如你可以将另一个脚本导入到worker中并使用以下两行打印出worker作用域的导航器对象的内容:
importScripts(foo.js);
console.log(navigator);2.7 WorkerLocation
WorkerLocation接口定义了Worker执行的脚本的绝对位置。这样的对象为每个worker初始化并通过WorkerGlobalScope可用。通过调用self.location获得的Location属性。
2.8 WorkerNavigator
WorkerNavigator接口表示允许从 Worker 访问的Navigator接口的一个子集。这样的对象为每个Worker初始化并通过self.navigator属性可用。