xgqfrms™, xgqfrms® : xgqfrms's offical website of cnblogs! xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!

前端性能优化系列之 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&copy; 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, 禁止转载 🈲️,侵权必究⚠️!


posted @ 2022-10-06 14:40  xgqfrms  阅读(303)  评论(3编辑  收藏  举报