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


  • 相关阅读:
    【Elasticsearch 技术分享】—— ES 常用名词及结构
    【Elasticsearch 技术分享】—— Elasticsearch ?倒排索引?这都是什么?
    除了读写锁,JUC 下面还有个 StampedLock!还不过来了解一下么?
    小伙伴想写个 IDEA 插件么?这些 API 了解一下!
    部署Microsoft.ReportViewe
    关于TFS强制undo他人check out
    几段查看数据库表占用硬盘空间的tsql
    How to perform validation on sumbit only
    TFS 2012 Disable Multiple Check-out
    在Chrome Console中加载jQuery
  • 原文地址:https://www.cnblogs.com/xgqfrms/p/16756914.html
Copyright © 2020-2023  润新知