📜  Javascript 中的网络工作者

📅  最后修改于: 2022-05-13 01:56:25.268000             🧑  作者: Mango

Javascript 中的网络工作者

Web Worker 让我们有可能编写多线程 Javascript,它不会阻塞 DOM。甚至异步操作也会在一定程度上阻塞 DOM。另一方面,Web Workers 帮助我们解决了这个问题,摆脱了单线程环境,达到了我们网页的更高性能。

为了使用:

  • 网络工作者住在他们自己的文件中(不与用户界面交互)
  • 函数通过副本传递
  • 不允许使用全局变量

    实现网络工作者

    /* -----------------------------Index.JS--------------------------*/
      
      // Check if web worker functionality is available for the browser
            if(window.Worker){
              
                // Creating new web worker using constructor
                var worker = new Worker('worker.js');
                  
                  
                var message = 'Hello';
              
                // Sending the message using postMessage
                worker.postMessage(message);
                  
                // On response
                worker.onmessage = function(e) {
                    console.log(e.data);
                };
              
            }
      
      
    /* -----------------------------Worker.JS--------------------------*/
      
    // Waits for any activity from the page
    self.onmessage = function(e) {
        if(e.data !== undefined) {
            // Do work 
            var total = e.data + ' World';
            // Posting back to the page
            self.postMessage(total)
        }
    }
    // Terminate with: worker.terminate()
    

    在上面的示例中,worker 正在将接收到的字符串与定义的字符串连接起来,并将其发送回 main.js 文件,而不会中断页面。

    Output :'Hello World'
    

    Web Workers 无权访问:

  • 父对象
  • 窗口对象
  • 文档对象
  • DOM

    但是,确实可以访问:

  • 定位对象
  • 导航器对象
  • XMLHttpRequest
  • 应用程序缓存
  • 产生其他网络工作者(存储在与父页面相同的来源)
  • 使用 importScripts() 导入外部脚本

    常见用例:

  • 当需要复杂的计算计算时
  • 在 HTML5 游戏中(更高帧率)
  • 在任何包含 JavaScript 以提高性能的网站上


    现实世界的例子

    编写以下程序的原因是为了显示我们的页面在有和没有工人的情况下的行为有什么不同。

    /* -----------------------------Index.JS--------------------------*/
    const delay = 5000;
      
    // Get element of without worker button
    const noWorkerBtn = document.getElementById('worker--without');
    // Add event listener to the button itself
    noWorkerBtn.addEventListener('click', () => {
        // Define the starting time
        const start = performance.now();
        // Do complex calculations
        while (performance.now() - start < delay);
        // Get the ending time
        const end = performance.now();
        // Calculate the difference in time
        const resWithoutWorker = end - start;
        // Log the result
        console.log('No worker:', resWithoutWorker);
          
    });
      
    // Define a worker
    const worker = new Worker('./worker.js');
      
    // Get element of with worker button
    const workerBtn = document.getElementById('worker--with');
      
    // Add event listener to the button
    workerBtn.addEventListener('click', () => {
        // Send delay number
        worker.postMessage(delay);
          
    });
    // On message from worker
    worker.onmessage = e => {
        // Log the result
        console.log("With worker: ", e.data);
    };
      
    /* -----------------------------Worker.JS--------------------------*/
      
    // On message received
    this.onmessage = e => {
        // Delay equals to data received
        const delay = e.data;
        // Define starting time
        const start = performance.now();
        // Do the complex calculation
        while (performance.now() - start < delay);
        // Get ending time
        const end = performance.now();
        // Calculate difference
        const resWithWorker = end - start;
        // Send result
        this.postMessage(end - start);
    };
    

    例子:

    Output: 'No worker: 5000'
    Output: 'With worker:  5000'
    

    这就是没有我们的工作代码时页面的行为方式:

  • 动画冻结是因为 JavaScript 阻塞了DOM
    没有 Web Worker 的复杂计算

    没有 webworker 的页面行为

    这就是页面在我们的工作代码中的行为方式:

  • 正如你所看到的,后台的动画没有被中断,因为我们的工作人员为我们进行了计算。这样,我们就让 DOM 线程独立运行了。
    使用 Web Worker 进行复杂计算

    webworker 的页面行为