Web Workers 草案翻译

发布于 2022-11-23 16:50:44 字数 7599 浏览 104 评论 1

基于 11.27 日的草案版本,在线地址

摘要

这份 Spec 定义了一个 API,这个 API 使 Web 应用开发者能够生成与他们的主页面并行的、在后台运行的 worker 脚本。这也使得,只要将消息传递作为协作机制,就能实现类线程的操作。

1. 简介

1.1. 范畴

本节是非正式的

这份 Spec 定义了一个用于运行与用户界面脚本独立的后台脚本的API。

这使得持续运行一些脚本,而不被响应点击或者其他用户交互的脚本打断,成为可能。而且,也使得长时任务可以被持续运行,而不用让出调度权来使得页面保持响应性。

Worker(这些后台脚本就叫这个)是相对而言比较重的,并且也不想被大规模地创建出来。例如,为一个4M大小的图片的每个像素创建一个worker是不合适的。下面的例子将展示一些worker恰当的用法。

一般而言,worker 具有较长的存活期,有一个比较大的启动性能开销并且每个实例有略高的内存消耗。

1.2. 示例

本节是非正式的

worker有许多用途。下述子章节展示了几种用途。

1.2.1. 进行后台数值运算的worker

本节是非正式的

worker最简单的用途是,运行计算密集型任务而不打断用户的交互。在这个例子中,主文档派生一个worker(naively)来计算素数,并展示最近被找到的素数。住文档页面如下所述:示例1 main.html

<!DOCTYPE HTML>
<html>
 <head>
  <title>Worker example: One-core computation</title>
 </head>
 <body>
  <p>The highest prime number discovered so far is: <output></output></p>
  <script>
   var worker = new Worker('worker.js');
   worker.onmessage = function (event) {
     document.getElementById('result').textContent = event.data;
   };
  </script>
 </body>
</html>

调用 Worker() 构造器将会创建一个 worker,并返回一个 Worker 对象用于表示 worker,该对象被用于和 worker 通信。返回对象的 onmessage 事件 handler 将使得代码可以从 worker 接收消息。

worker本身的代码如下所述:示例2 worker.js

var n = 1;
search: while (true) {
  n += 1;
  for (var i = 2; i <= Math.sqrt(n); i += 1)
    if (n % i == 0)
     continue search;
  //  找到素数
  postMessage(n);
}

The bulk of this code is simply an unoptimised search for a prime number. The postMessage() method is used to send a message back to the page when a prime is found.
这份代码中的大部分都只是未经优化的素数搜索。postMessage() 方法被用于找到新素数后向页面回传数据。

1.2.2. 用于后台 I/O 的 worker

本节是非正式的

在这个示例中,主文档使用了两个 worker,一个用于以固定地频率获取股票更新,而另一个用于处理用户请求的搜索查询。主页面代码如下 示例3 main.html

<!DOCTYPE HTML>
<html>
 <head>
  <title>Worker example: Stock ticker</title>
  <script>
   // Ticker
   var symbol = 'GOOG'; // default symbol to watch
   var ticker = new Worker('ticker.js');

   // Searcher
   var searcher = new Worker('searcher.js');
   function search(query) {
     searcher.postMessage(query);
   }

   // Symbol selection UI
   function select(newSymbol) {
     symbol = newSymbol;
     ticker.postMessage(symbol);
   }
  </script>
 </head>
 <body onload="search('')">
  <p><output></output> <output></output></p>
  <script>
   ticker.onmessage = function (event) {
     var data = event.data.split(' ');
     document.getElementById('symbol').textContent = data[0];
     document.getElementById('value').textContent = data[1];
   };
   ticker.postMessage(symbol);
  </script>
  <p><label>Search: <input type="text" autofocus oninput="search(this.value)"></label></p>
  <ul></ul>
  <script>
   searcher.onmessage = function (event) {
     var data = event.data.split(' ');
     var results = document.getElementById('results');
     while (results.hasChildNodes()) // Clear previous results
       results.removeChild(results.firstChild);
     for (var i = 0; i < data.length; i += 1) {
       // Add a list item with a button for each result
       var li = document.createElement('li');
       var button = document.createElement('button');
       button.value = data[i];
       button.type = 'button';
       button.onclick = function () { select(this.value); };
       button.textContent = data[i];
       li.appendChild(button);
       results.appendChild(li);
     }
   };
  </script>
  <p>(The data in this example is not real. Try searching for "Google" or "Apple".)</p>
 </body>
</html>

这两个worker使用了一个公共的库来进行实际的网络请求。这个库如下所示:示例4 io.js

function get(url) {
  try {
    var xhr = new XMLHttpRequest();
    xhr.open('GET', url, false);
    xhr.send();
    return xhr.responseText;
  } catch (e) {
    return ''; // Turn all errors into empty results
  }
}

股票更新的 worker 如下所述:示例5 ticker.js

importScripts('io.js');
var timer;
var symbol;
function update() {
  postMessage(symbol + ' ' + get('stock.cgi?' + symbol));
  timer = setTimeout(update, 10000);
}
onmessage = function (event) {
  if (timer)
    clearTimeout(timer);
  symbol = event.data;
  update();
};

搜索查询的 worker 代码如下所示:示例6 search.js

importScripts('io.js');
onmessage = function (event) {
  postMessage(get('search.cgi?' + event.data));
};

1.2.3. shared worker 简介

本节是非正式的

本节用一个 Hello World 的示例介绍了 shared worker。shared worker 使用一些稍微不同的 API,因为每个 woker 都可能有多个连接。第一个示例展示了你该怎样连接一个 worker,以及一个 worker 如何在页面连接上它的时候回传信息。接收道德消息将在 log 中展示。

下面是 HTML 页面:示例7 main.html

<!DOCTYPE HTML>
<title>Shared workers: demo 1</title>
<pre>Log:</pre>
<script>
  var worker = new SharedWorker('test.js');
  var log = document.getElementById('log');
  worker.port.onmessage = function(e) { // Note: Not worker.onmessage!
    log.textContent += 'n' + e.data;
  }
</script>

下面是 js 代码 示例8 test.js

onconnect = function(e) {
  var port = e.ports[0];
  port.postMessage('Hello World!');
}

通过改变两件事,第二个例子扩展了第一个示例。首先,消息用 addEventListener() 接收而不是用 event handler 的 IDL 属性;其次,一个消息被发送给 worker,使得 worker 发回另一个消息。接收道德消息也将在 log 中展示。

下面是HTML代码:示例9 main.html

<!DOCTYPE HTML>
<title>Shared workers: demo 2</title>
<pre>Log:</pre>
<script>
  var worker = new SharedWorker('test.js');
  var log = document.getElementById('log');
  worker.port.addEventListener('message', function(e) {
    log.textContent += 'n' + e.data;
  }, false);
  worker.port.start(); // Note: Needed when using addEventListener
  worker.port.postMessage('ping');
</script>

这是 worker 的代码:示例10 test.js

onconnect = function(e) {
  var port = e.ports[0];
  port.postMessage('Hello World!');
  port.onmessage = function(e) {
    port.postMessage('pong'); // Not e.ports[0].postMessage!
    // e.target.postMessage('pong'); // Also works
  }
}

最后这个例子被扩展到展示两个页面如何与同一个 worker 通信;在这个例子中下,第二个页面仅仅是第一个页面的一个 iframe,但是在一个完全独立的独立定级浏览上下文(就是浏览器的不同窗口 / 标签页)中也有相同的原理。

这是外层的 html 页面:示例11

<!DOCTYPE HTML>
<title>Shared workers: demo 3</title>
<pre>Log:</pre>
<script>
  var worker = new SharedWorker('test.js');
  var log = document.getElementById('log');
  worker.port.addEventListener('message', function(e) {
    log.textContent += 'n' + e.data;
  }, false);
  worker.port.start();
  worker.port.postMessage('ping');
</script>
<iframe src="inner.html"></iframe>

这是内层的 html 页面:示例12

<!DOCTYPE HTML>
<title>Shared workers: demo 3 inner frame</title>
<pre id=log>Inner log:</pre>
<script>
  var worker = new SharedWorker('test.js');
  var log = document.getElementById('log');
  worker.port.onmessage = function(e) {
   log.textContent += 'n' + e.data;
  }
</script>

这是 worker 的代码:示例13

var count = 0;
onconnect = function(e) {
  count += 1;
  var port = e.ports[0];
  port.postMessage('Hello World! You are connection #' + count);
  port.onmessage = function(e) {
    port.postMessage('pong');
  }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

┈┾☆殇 2022-05-02 00:41:57

翻译规范真是累活啊

~没有更多了~

关于作者

神经大条

暂无简介

0 文章
0 评论
23 人气
更多

推荐作者

醉城メ夜风

文章 0 评论 0

远昼

文章 0 评论 0

平生欢

文章 0 评论 0

微凉

文章 0 评论 0

Honwey

文章 0 评论 0

qq_ikhFfg

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文