Web Workers 草案翻译
基于 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 技术交流群。
上一篇: Node 原生模块杂谈
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
翻译规范真是累活啊