前端性能优化系列之 Web Workers 实战教程 All In One
前端性能优化系列之 Web Workers 实战教程 All In One
background thread / main thread
background task / 后台任务
https://caniuse.com/?search=Web Workers
98.41%
✅
https://html.spec.whatwg.org/multipage/workers.html
Web Workers
https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API
除了标准的 JavaScript 函数集(例如 String、Array、Object、JSON 等)之外,您几乎可以在工作线程中运行您喜欢的任何代码。
有一些例外:例如,您不能直接从 worker 内部操作 DOM,或者使用窗口对象的一些默认方法和属性。
https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API#worker_global_contexts_and_functions
https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API#supported_web_apis
https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers
Worker
https://developer.mozilla.org/en-US/docs/Web/API/Worker
https://developer.mozilla.org/en-US/docs/Web/API/Worker/Worker
postMessage
https://developer.mozilla.org/en-US/search?q=postMessage
Worker.postMessage()
https://developer.mozilla.org/en-US/docs/Web/API/Worker/postMessage
Window.postMessage()
https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage
Client.postMessage()
https://developer.mozilla.org/en-US/docs/Web/API/Client/postMessage
Web Workers 应用场景
大量数据运算
大型 3D 模型加载
游戏
...
demos
<!DOCTYPE html>
<html lang="zh-Hans">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<meta name="author" content="xgqfrms">
<meta name="generator" content="VS code">
<title>Web Workers</title>
</head>
<body>
<header>
<h1>Web Workers</h1>
</header>
<main>
<section>
<a href="https://learning.xgqfrms.xyz/HTML5/Web-Workers/index.html">https://learning.xgqfrms.xyz/HTML5/Web-Workers/index.html</a>
</section>
</main>
<footer>
<p>copyright© xgqfrms 2022</p>
</footer>
<script src="./main.js"></script>
</body>
</html>
"use strict";
/**
*
* @author xgqfrms
* @license MIT
* @copyright xgqfrms
* @created 2022-01-01
* @modified
*
* @description
* @augments
* @example
* @link
* @solutions
*
* @best_solutions
*
*/
const log = console.log;
// 实例化
const webWorker = new Worker(`./web-workers.js`);
log(`\nwebWorker =`, webWorker);
// log(`\nwebWorker name =`, webWorker.name);
// undefined
webWorker.addEventListener(`message`, (msg) => {
log(`\n✅主线程 收到 message =`, msg);
});
// 等价于
webWorker.onmessage = ((msg) => {
log(`✅✅主线程 收到 message =`, msg);
});
webWorker.addEventListener(`error`, (err) => {
log(`\n❌主线程 收到 error =`, err);
});
// 等价于
webWorker.onerror = ((err) => {
log(`❌❌主线程 收到 error =`, err);
});
webWorker.addEventListener(`messageerror`, (err) => {
log(`\n❌主线程 收到 messageerror =`, err);
});
// 等价于
webWorker.onmessageerror = ((err) => {
log(`❌❌主线程 收到 messageerror =`, err);
});
webWorker.postMessage(`🚀主线程 发送 message`);
webWorker.postMessage({
msg: '🚀🚀主线程 发送 message',
});
setTimeout(() => {
// throw new Error(`手动触发 error`);
log(`主线程 手动终止 后台线程 🔒`)
webWorker.terminate();
}, 3000);
// setTimeout(() => {
// // throw new Error(`手动触发 error`);
// log(`主线程 手动终止 后台线程 🔒`)
// webWorker.terminate();
// }, 4000);
// 手动终止后台线程
// webWorker.terminate();
"use strict";
/**
*
* @author xgqfrms
* @license MIT
* @copyright xgqfrms
* @created 2022-01-01
* @modified
*
* @description
* @augments
* @example
* @link
* @solutions
*
* @best_solutions
*
*/
const log = console.log;
// 实例化
log(`\n👻 Web Worker self =`, self);
// log(`Web Worker self.name =`, self.name);
// undefined
// 自定义 name
self.name = `web workers`;
log(`\n👻 self.name =`, self.name);
// web workers
// ❌ Uncaught TypeError: self is not iterable
// for (const prop of self) {
// if(self.hasOwnProperty(prop)) {
// log(`self.${prop} =`, prop);
// }
// }
for (const prop in self) {
if(self.hasOwnProperty(prop)) {
// log(`self.${prop} =`, prop);
}
}
/*
self.name = name
self.onmessage = onmessage
self.onmessageerror = onmessageerror
self.close = close
self.postMessage = postMessage
self.requestAnimationFrame = requestAnimationFrame
self.cancelAnimationFrame = cancelAnimationFrame
self.webkitRequestFileSystem = webkitRequestFileSystem
self.webkitRequestFileSystemSync = webkitRequestFileSystemSync
self.webkitResolveLocalFileSystemSyncURL = webkitResolveLocalFileSystemSyncURL
self.webkitResolveLocalFileSystemURL = webkitResolveLocalFileSystemURL
*/
self.addEventListener(`message`, (messageEvent) => {
// MessageEvent
log(`\n✅后台线程 收到 message =`, messageEvent.data);
});
// 等价于
self.onmessage = ((messageEvent) => {
// MessageEvent
log(`✅✅后台程 收到 message =`, messageEvent.data);
});
self.addEventListener(`error`, (err) => {
log(`\n❌后台线程 收到 error =`, err);
});
// 等价于
self.onerror = ((err) => {
log(`❌❌后台线程 收到 error =`, err);
});
self.addEventListener(`messageerror`, (err) => {
log(`\n❌后台线程 收到 messageerror =`, err);
});
// 等价于
self.onmessageerror = ((err) => {
log(`❌❌后台线程 收到 messageerror =`, err);
});
self.postMessage(`🚀后台线程 发送 message`);
self.postMessage({
msg: '🚀🚀后台线程 发送 message',
});
// setTimeout(() => {
// // throw new Error(`手动触发 error`);
// log(`手动关闭 后台线程 🔒`)
// self.close();
// }, 3000);
// setTimeout(() => {
// // throw new Error(`手动触发 error`);
// log(`手动关闭 后台线程 🔒`)
// self.close();
// }, 4000);
// 手动关闭
// self.close();
"use strict";
/**
*
* @author xgqfrms
* @license MIT
* @copyright xgqfrms
* @created 2022-01-01
* @modified
*
* @description
* @augments
* @example
* @link
* @solutions
*
* @best_solutions
*
*/
const log = console.log;
// 实例化
log(`\n👻 Web Worker self =`, self);
// DedicatedWorkerGlobalScope
log(`self === this:`, self === this, this);
// self === this: true
// log(`Web Worker self.name =`, self.name);
// undefined
// 自定义 name
// self.name = `web workers`;
// this.name = `web workers`;
name = `web workers`;
log(`\n👻 name =`, self.name, this.name, name);
// web workers
// ❌ Uncaught TypeError: self is not iterable
// for (const prop of self) {
// if(self.hasOwnProperty(prop)) {
// log(`self.${prop} =`, prop);
// }
// }
for (const prop in self) {
if(self.hasOwnProperty(prop)) {
// log(`self.${prop} =`, prop);
}
}
/*
self.name = name
self.onmessage = onmessage
self.onmessageerror = onmessageerror
self.close = close
self.postMessage = postMessage
self.requestAnimationFrame = requestAnimationFrame
self.cancelAnimationFrame = cancelAnimationFrame
self.webkitRequestFileSystem = webkitRequestFileSystem
self.webkitRequestFileSystemSync = webkitRequestFileSystemSync
self.webkitResolveLocalFileSystemSyncURL = webkitResolveLocalFileSystemSyncURL
self.webkitResolveLocalFileSystemURL = webkitResolveLocalFileSystemURL
*/
// WorkerNavigator
log(`\nself.navigator =`, self.navigator);
log(`navigator =`, navigator);
// ❌ Uncaught ReferenceError: locationbar is not defined
// log(`locationbar =`, locationbar);
// ❌ Uncaught ReferenceError: localStorage is not defined
// log(`localStorage =`, localStorage);
// ❌ Uncaught ReferenceError: cacheStorage is not defined
// log(`cacheStorage =`, cacheStorage);
log(`caches =`, caches);
// CacheStorage {}
log(`location =`, location);
// WorkerLocation {origin: 'http://127.0.0.1:5500', protocol: 'http:', host: '127.0.0.1:5500', hostname: '127.0.0.1', port: '5500', …}
log(`location.origin =`, location.origin);
log(`origin =`, origin);
// location.origin = http://127.0.0.1:5500
// origin = http://127.0.0.1:5500
log(`indexedDB =`, indexedDB);
// IDBFactory {}
log(`isSecureContext =`, isSecureContext);
log(`performance =`, performance);
// Performance {timeOrigin: 1665238487506.5, onresourcetimingbufferfull: null}
log(`console =`, console);
// console {debug: ƒ, error: ƒ, info: ƒ, log: ƒ, warn: ƒ, …}
log(`crossOriginIsolated =`, crossOriginIsolated);
// false
log(`onlanguagechange =`, onlanguagechange);
log(`onrejectionhandled =`, onrejectionhandled);
log(`onunhandledrejection =`, onunhandledrejection);
// onlanguagechange = null
// onrejectionhandled = null
// onunhandledrejection = null
log(`decodeURI =`, decodeURI);
log(`encodeURI =`, encodeURI);
log(`decodeURIComponent =`, decodeURIComponent);
log(`encodeURIComponent =`, encodeURIComponent);
// decodeURI = ƒ decodeURI() { [native code] }
// encodeURI = ƒ encodeURI() { [native code] }
// decodeURIComponent = ƒ decodeURIComponent() { [native code] }
// encodeURIComponent = ƒ encodeURIComponent() { [native code] }
log(`escape =`, escape);
log(`unescape =`, unescape);
log(`eval =`, eval);
// escape = ƒ escape() { [native code] }
// unescape = ƒ unescape() { [native code] }
// eval = ƒ eval() { [native code] }
log(`scheduler =`, scheduler);
// Scheduler {}
log(`trustedTypes =`, trustedTypes);
// TrustedTypePolicyFactory {emptyHTML: emptyHTML "", emptyScript: emptyScript "", defaultPolicy: null}
log(`globalThis =`, globalThis);
// DedicatedWorkerGlobalScope
log(`self =`, self);
// DedicatedWorkerGlobalScope
log(`🚀 `, self === globalThis, globalThis === this, this === self);
// true true true
for (const item of [atob, btoa, createImageBitmap, fetch, setInterval, setTimeout, clearInterval, clearTimeout]) {
log(`${item} =`, item);
// WorkerGlobalScope
// ❌ Uncaught TypeError: Failed to execute 'atob' on 'WorkerGlobalScope': 1 argument required, but only 0 present.
// log(`${item}() =`, item());
}
self.addEventListener(`message`, (messageEvent) => {
// MessageEvent
log(`\n✅后台线程 收到 message =`, messageEvent.data);
});
// 等价于
// self.onmessage = (messageEvent) => {
// // MessageEvent
// log(`✅✅后台线程 收到 message =`, messageEvent.data);
// };
// 等价于
// this.onmessage = (messageEvent) => {
// // MessageEvent
// log(`✅✅✅后台线程 收到 message =`, messageEvent.data);
// };
// 等价于
onmessage = (messageEvent) => {
// MessageEvent
log(`✅✅✅✅后台线程 收到 message =`, messageEvent.data);
};
self.addEventListener(`error`, (event) => {
// Event
log(`\n❌后台线程 收到 error =`, event);
});
// 等价于
self.onerror = (event) => {
// Event
log(`❌❌后台线程 收到 error =`, event);
};
self.addEventListener(`messageerror`, (err) => {
log(`\n❌后台线程 收到 messageerror =`, err);
});
// 等价于
self.onmessageerror = (err) => {
log(`❌❌后台线程 收到 messageerror =`, err);
};
// MessageEvent.data
self.postMessage(`🚀后台线程 发送 message`);
self.postMessage({
msg: '🚀🚀后台线程 发送 message',
});
// setTimeout(() => {
// // throw new Error(`手动触发 error`);
// log(`手动关闭 后台线程 🔒`)
// self.close();
// }, 3000);
// setTimeout(() => {
// // throw new Error(`手动触发 error`);
// log(`手动关闭 后台线程 🔒`)
// self.close();
// }, 4000);
// 手动关闭
// self.close();
live demo
https://learning.xgqfrms.xyz/HTML5/Web-Workers/index.html
Service Workers
https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API
https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API/Using_Service_Workers
refs
https://github.com/xgqfrms/leetcode/tree/master/000-xyz/Workers
https://github.com/xgqfrms/learning-javascript-with-mdn/issues/28
OffscreenCanvas
https://developer.mozilla.org/en-US/docs/Web/API/OffscreenCanvas
https://zhuanlan.zhihu.com/p/34698375
https://zhuanlan.zhihu.com/p/30534023
AMP WorkerDOM
https://amphtml.wordpress.com/2018/08/21/workerdom/
https://developer.mozilla.org/en-US/docs/Web/API/WorkerGlobalScope
https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver
https://developer.mozilla.org/en-US/docs/Web/API/MutationRecord
©xgqfrms 2012-2020
www.cnblogs.com/xgqfrms 发布文章使用:只允许注册用户才可以访问!
原创文章,版权所有©️xgqfrms, 禁止转载 🈲️,侵权必究⚠️!
本文首发于博客园,作者:xgqfrms,原文链接:https://www.cnblogs.com/xgqfrms/p/16756914.html
未经授权禁止转载,违者必究!