多线程Javascript深入了解 Web Worker

您可能知道,Javascript 是单线程的。为了更好地说明,这意味着一个线程处理事件循环。对于旧版浏览器,整个浏览器在所有选项卡之间共享一个线程。现代浏览器通过使用每个站点实例的进程或每个选项卡的不同线程对此进行了改进。尽管专用线程提高了网页的响应速度,但它仍然让每个选项卡无法同时处理多个脚本运行。

您可能想知道,为什么我们需要同时运行多个脚本?

计算机速度非常快,每个选项卡都使用自己的线程,网页应该没有问题。大多数情况下都是如此,直到您的浏览器运行复杂的算法或呈现复杂的可视化效果。这些费力的过程最终会阻塞主线程,从而减慢 UI 事件和触发器的速度。好在 2009 年,Javascript 推出了一个热门的新玩具 Web Workers 来解决这个问题。

那么什么是 Web Worker?

Web Workers 是从 HTML 页面执行的 Javascript 脚本,该页面在远离主执行线程的后台线程上运行。数据通过消息在主线程和工作线程之间发送。由于这些 worker 在与主执行线程不同的线程上运行,因此您可以利用 web worker 从浏览器运行处理密集型任务,而无需创建阻塞实例。

酷吧?让我们建造一些。

生成 Web Worker 非常简单。首先,我们需要从两个文件开始:一个主文件和一个包含工作程序将运行的代码的文件。单独的文件是必需的,因为 Web 工作者代码需要在隔离的线程中运行。让我们将文件命名为 main.js 和 worker.js。要创建一个新的 Worker 对象,我们会将 worker 文件的路径传递给 Worker 构造函数,如下所示:

//main.js
var worker = new Worker('worker.js');

现在我们有了一个工人,让我们向它发送一条消息。为此,我们必须调用 worker 对象的 postMessage() 函数。

//main.js
var worker = new Worker('worker.js');
worker.postMessage('生日快乐');

在这一点上,我可能应该指出网络工作者的警告。主线程和工作线程之间发送的数据被复制而不是共享. 在考虑内存分配和数据传输速度时,我们应该牢记这一点。

现在为了让我们的工作人员听到“生日快乐”消息,我们必须在 worker.js 文件中为消息事件设置一个事件侦听器。

//worker.js
self.addEventListener('message', function(e) { 
  // 要运行的代码
}

一旦工作文件听到消息事件,它就会运行功能块中的代码。就像任何其他普通函数一样编写它,但不是返回变量,而是使用 postMessage() 函数将消息发送回主线程。我们可以将已发送消息中的数据与 e.data 一起使用。

//worker.js
self.addEventListener('message', function(e) { 
  var message = e.data + 'to myself!'; 
  self.postMessage(message); 
}

在上面的代码中,我们发送消息“祝我生日快乐!” 回到主执行线程。因此,我们还需要在主文件中有一个消息事件侦听器来接收数据并对其进行操作。这是最终的 main.js 文件:

//main.js
var worker = new Worker('worker.js');
worker.addEventListener('message', function(e) { 
  console.log(e.data); 
}
worker.postMessage('生日快乐');

在此示例中,我们将 console.log '祝我生日快乐!'。一个有用的提示是,虽然 worker.addEventListener 和 worker.postMessage 的顺序无关紧要,但我们在发送消息之前创建监听消息的能力是合乎逻辑的。

最后我们想关闭工作线程,我们可以在工作文件中添加一个 self.close() 函数。这是最终的 worker.js:

//worker.js
self.addEventListener('message', function(e) { 
  var message = e.data + 'to myself!'; 
  self.postMessage(message); 
  self.close(); 
}

让我们回顾一下刚刚发生的事情:

  1. 我们的应用程序在 main.js 中创建了一个网络工作者,它运行来自 worker.js 的代码

  1. 它向工作人员发送一条包含字符串“生日快乐”的消息

  1. 具有“消息”事件侦听器的工作人员接收到消息并运行其中的代码。

  1. 工人附加了“我自己!” 消息数据创建“祝我生日快乐!” 并将其作为消息中的数据发送回 main.js

  1. Main.js,它也有一个消息事件监听器,而不是 console.log '祝我生日快乐!'。

简单!

以下代码使用 web worker 来拆分解决 n-queens 的处理过程:

//nQueen.html 
<!DOCTYPE html>
<html>

<head>
  <title>n-queens solver</title>
</head>

<body>
  <script type="src/queenWorker.js"></script>
  <script>
  var num = parseInt(prompt("enter num"));
  var all = (1 << num) - 1;
  count = 0;
  for (var i = 0; i < num; i++) {
    var cols = 2 ** i;
    var ld = 2 ** (i + 1);
    var rd = 0;
    if (i > 0) {
      rd = 2 ** (i - 1);
    }
    var myWorker = new Worker('queenWorker.js');
    myWorker.addEventListener('message', function(e) {
      count += e.data;
      console.log('worker count: ', e.data);
    }, false);
    myWorker.postMessage([ld, cols, rd, all]);
  }
  
  </script>
</body>

</html>
//queenWorker.js 
self.addEventListener('message', function(e) {
  let count = 0;
  var findSolutions = function(ld, cols, rd, all) {
    let poss = ~(ld | cols | rd) & all;
    if (cols === all) {
      count++;
    }
    while (poss) {
      let negPoss = poss * -1;
      let bit = poss & negPoss;
      //let bit = poss & -poss;
      poss = poss - bit;
      findSolutions((ld | bit) << 1, cols | bit, (rd | bit) >> 1, all);
    }
  };
  findSolutions(e.data[0], e.data[1], e.data[2], e.data[3]);
  self.postMessage(count);
}, false);

随意玩弄它!测试 web workers 的注意事项,出于安全原因,Chrome 不允许您在本地部署 web workers。请改用 Firefox。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Vue 3支持Web Worker多线程的特性,这是一种在浏览器中运行JavaScript代码的方式,可以在后台运行独立的线程,提高应用程序性能和响应能力。 在Vue 3中,可以使用`Vue. createApp()`方法创建Vue实例,并使用`createWebWorker`方法将其转换为Web Worker。这个方法接收一个参数,指定Worker脚本的URL或者内联函数的URL。例如: ```javascript const app = Vue.createApp({...}); const worker = app.createWebWorker('path-to-worker-script.js'); ``` 然后,可以使用`worker`对象的方法与Web Worker进行通信。例如,通过`postMessage`方法发送消息给Worker线程: ```javascript worker.postMessage({ data: 'message' }); ``` 同时,还可以通过`onmessage`事件监听来自Worker线程的消息: ```javascript worker.onmessage = function(event) { const data = event.data; // 处理接收到的消息 }; ``` 在Worker线程中,可以使用`self`关键字引用Worker对象,同样可以通过`postMessage`方法发送消息给主线程,并通过`onmessage`事件处理来自主线程的消息。 Web Worker多线程功能可以极大地提高Vue应用程序的性能和响应能力,将一些耗时的操作(如计算、渲染等)放在Worker线程中运行,避免阻塞主线程,提高用户体验。 需要注意的是,在使用Web Worker时,需要考虑到跨域访问的限制,以及数据传输的序列化和反序列化等问题。在实际应用中,需要根据具体需求和场景合理使用Web Worker多线程功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值