I. What are Web Workers
Web Workers are a mechanism that supports tasks running in background threads. That's right, Web Worker provides restricted multi-threading.
Although the JavaScript execution environment in browsers is still single-threaded, multi-threading has long existed in browsers. For example, async XHR is a restricted thread that is independent of the main thread and communicates via built-in messaging mechanisms, without the concurrency problems of general multi-threading.
Web Workers provide a context independent of the main thread, where restricted APIs can be used (DOM manipulation is prohibited, Cache access might be unavailable, etc.). The biggest benefit of multi-threading is that it doesn't block the UI. Multi-threading can be used to complete time-consuming tasks (such as audio/video decoding, and data processing based on this). Even if the API allows, utilizing Web Workers could allow you to implement XHR yourself.
P.S. Whether Web Workers are allowed to access Cache is currently (2015/11/29) still controversial. Chrome43 and FF support it; IE and Safari support is unknown.
A bit of nonsense: Google's Gears plugin proposed the Worker Pool API, which is the "prototype" of Web Workers. Initially, it was hoped to enhance browser functionality, such as supporting offline browsing (accessing cached pages offline, submitting offline operations after reconnecting), but as of now (2015/11/29) it has been deprecated.
Google Gears API
The Google Gears API is no longer available. Thank you for your interest.
II. What are Web Workers used for
Background threads are primarily used for do stuff. Supporting background threads means browsers can undertake more and heavier tasks. Some computations originally borne by the server (such as sorting, encoding/decoding, template generation) can be handed over to the client to reduce server pressure, without affecting user experience (waiting for the server to return results and waiting for another local thread to return results are both waiting, and the latter may be faster).
The author believes Web Workers have the following applicable scenarios:
- Audio/Video decoding
If you have tried operations like audioContext.decodeAudioData, you will realize that we urgently need a background thread that can "do heavy lifting"
- Image preprocessing
For example, cropping before avatar upload, or even adding watermarks, compositing, adding mosaics. If these can be completed on the client side, it can avoid a large amount of temporary file transmission
- Sorting and other data processing algorithms
Reduce server pressure
- Client-side templates
For example, markdown, or the server returns JSON, and the client hands it over to a background thread to parse and apply template HTML to generate the page. If these operations are all completed by the client, there is less to transmit
III. How to use Web Workers
The explanatory code example is as follows:
//---主页面
if (window.Worker) {
var worker = new Worker('worker.js');
var data = {a: 1, b: [1, 2, 3], c: 'string'};
worker.postMessage(data);
worker.onmessage = function(e) {
console.log('main thread received data');
console.log(e.data);
// 接到消息立即停止 worker,onerror 将不会触发
// worker.terminate();
// terminate 之后收不到后续消息,但 post 不报错
// worker.postMessage(1);
}
worker.onerror = function(err) {
console.log('main thread received err');
console.log(err.message);
// 阻止报错
err.preventDefault();
}
}
//---end 主页面
//---worker.js
// 可以引入其它依赖
// importScripts('lib.js');
// importScripts('a.js', 'b.js');
onmessage = function(e) {console.log(self); // 看看 global 变量身上有些什么
var data = e.data;
console.log('worker received data');
console.log(data);
var res = data;
res.resolved = true;
postMessage(res);
setTimeout(function() {
throw new Error('error occurs');
// close,立即停止,相当于主线程中的 worker.terminate()
// close();
}, 100);
};
//---end worker.js
Note:
-
worker's global context is notwindow, butself.selfalso provides a series of interfaces, includingself.JSON,self.Math,self.console, etc. The most intuitive difference is that thedocumentobject is gone, butlocationandnavigatorare still there. -
Worker's prototype is DedicatedWorkerGlobalScope. Different from SharedWGS, Worker is dedicated; only the script that created the Worker can access the worker it created.
-
DOM manipulation is not allowed in
worker, but WebSocket, IndexedDB, XHR, etc. are supported. There are differences in browser support; for specifics please see Functions and classes available to Web Workers - Web APIs | MDN
Note: Although XHR can be used, the XHR object's responseXML and channel properties always return null.
-
The main thread and worker thread send and receive messages in the same way (
postMessageto send,onmessage/onerrorto receive, data is taken from thedataproperty of MessageEvent). What is passed between threads is a value copy, not a shared reference. -
IE10 and FF support new Worker inside
worker, as long as these workers are same-origin with the parent page. -
Regarding support issues, feature detection is recommended.
if (window.Worker) { // new Worker... } -
importScriptscan import other js files. Global variables in external files will be stuck onself, and can be directly referenced inworker.importScriptsis synchronous; the next line executes after downloading and execution is complete.
IV. Shared Worker
The Worker we focused on above belongs to dedicated worker, only the context that created the worker object has access rights to the worker. Shared Worker supports cross-context worker sharing, such as window with iframe, iframe with iframe.
Because they have shared attributes, they can maintain the same state of an application in different windows, and pages in different windows maintain and report state through the same shared worker script.
localStorage can also be used to achieve state synchronization. Senior zxx's example: Page Visibility API and Login Sync Guide Page Example Page. If interested, you can view the original text: Page Visibility API Introduction, Micro-extension
The only applicable scenario the author can think of for Shared Worker might be implementing an application state synchronization mechanism. Although cookies and localStorage can store state, Shared Worker can implement a complex state control mechanism. In short, cookies and localStorage can only store data; Shared Worker can store data and also execute code.
In addition, Shared Worker seems to be of little use. After all, being able to new Worker is already very good; the effect of something that is just icing on the cake won't be surprising.
The example code is as follows:
//---主页面
if (window.SharedWorker) {
var sworker = new SharedWorker('sharedworker.js');
// 1.onmessage 隐式调用 start
// sworker.port.onmessage = function(e) {
// console.log('main thread received data:');
// console.log(e.data);
// }
// 2.或者 addEventListener 再显式调用 start
sworker.port.addEventListener('message', function(e) {
console.log('main thread received data:');
console.log(e.data);
});
sworker.port.start();
sworker.port.postMessage([1, 2, 3]);
}
//---end 主页面
//---sharedworker.js
var count = 0;
onconnect = function(e) {
// 记录连接数
count++;
var port = e.ports[0];
// 1.onmessage 隐式调用 start
port.onmessage = function(e) {
//!!! console.log 失效了
console.log('will not occur in console');
port.postMessage({receivedData: e.data, count: count});
//!!! 错误不会抛回给 sharedworker 创建者,静默失败
//!!! 如果 sharedworker 本身有语法错误,也会静默失败,而且在这之前的 postMessage 也将无效
// a*; // 制造一个语法错误
setTimeout(function() {
throw new Error('error occurs');
}, 100);
};
// 2.或者 addEventListener 再显式调用 start
// port.addEventListener('message', function(e) {
// //!!! console.log 失效了
// console.log('will not occur in console');
// port.postMessage('sharedworker received data: ' + e.data);
// });
// port.start();
};
//---end sharedworker.js
Online DEMO: testSharedWorker DEMO
Test method: Open the link above, check console and find count is 1. No matter how you refresh, it's always 1. Open another tab to open the page, find count becomes 2. Then refresh refresh refresh, find count becomes 5. Go back to the previous tab, refresh, count becomes 6...
V. Thread Safety Issues
Regarding thread safety, various problems caused by concurrency do not exist, because Worker thread behavior is restricted (worker cannot access non-thread-safe components and DOM).
VI. Other Workers
Besides the Web Workers discussed above, there are these Workers:
-
ServiceWorkers (similar to proxy servers, providing offline services)
-
ChromeWorker (Worker available in browser plugin development)
-
Audio Workers (supports audio processing, no browser support yet, 2015/11/29)
Reference Materials
-
Using Web Workers - Web APIs | MDN: Do not look at the Chinese version, the translated content is outdated.
No comments yet. Be the first to share your thoughts.