Web Worker æä¾ç°¡å®çæ¹æ³è®ç¶²é å¨èæ¯å·è¡ç·ï¼Threadï¼ä¸å·è¡ç¨å¼ï¼èä¸å¹²æ¾ä½¿ç¨è
ä»é¢éè¡ï¼å¦å¤ï¼Worker ä¹å¯ä»¥å©ç¨ XMLHttpRequest
å·è¡è¼¸åº/輸å
¥ï¼ä½æ¯ responseXML å channel éå
©å屬æ§çº nullï¼ï¼ä¸å worker å¯ä»¥èç±äºä»¶èçå¨ä¾å web worker åµé 端äºç¸å³éè¨æ¯ï¼æ¥ä¸ä¾æ¬æææä¾ä½¿ç¨ web worker ç詳細說æã
éé worker 建æ§å (å¦ Worker()
) 便å¯ä»¥ç¢ç worker ç©ä»¶ï¼ä¸¦ä¸å·è¡ JavaScript æªæ¡ãå¨ worker ä¸ç JavaScript éè¡å¨ä¸åæ¼ window
çå·è¡ç·ç°å¢ï¼æä»¥å¨ worker ä¸ååå
¨åç©ä»¶æè©²è¦éé self
ï¼å¦æéé window
æå°è´é¯èª¤ç¼çã
Dedicated worker (å°æ worker) æ¯ä¸è¬ workerï¼åªè½è¢«ç¢çå®çæªæ¡ååï¼DedicatedWorkerGlobalScope
ç©ä»¶ä»£è¡¨å
¶å·è¡ç°å¢ï¼è Shared worker (å
±äº« worker) åè½å¤ 被ä¸åæªæ¡ååï¼SharedWorkerGlobalScope
) ç©ä»¶ä»£è¡¨å
¶å·è¡ç°å¢ã
åè¨»ï¼ worker å ¶ä»æä»¶èªªæè«è¦ The Web Workers API landing page ã
åºæ¬ä¸ worker è½å¤ å·è¡ä»»ä½äºæ
ï¼æ¯å¦èªª WebSocketsãIndexedDBãå Firefox OS ç¹æç Data Store API ï¼ç¶èç´æ¥åå DOM ææ¯ window
ç©ä»¶çä¸äºæ¹æ³å屬æ§åä¸è¢«å
è¨±ï¼æ´å¤ç´°ç¯è«è¦ worker å¯ååç¥å½æ¸åé¡å¥ã
主å·è¡ç·å worker å·è¡ç·ä¹éç¨ postMessage() æ¹æ³ç¼éè¨æ¯ï¼ç¶å¾éé onmessage
äºä»¶æ¥åè¨æ¯ (è¨æ¯åå¨ message
äºä»¶ç data 屬æ§ä¹ä¸)ï¼å
¶ä¸è¢«å³éçè³æä¸¦éå
±äº«èæ¯è¤è£½ä¸ä»½å¾å³éã
worker å¯ä»¥ç¢çæ° workerï¼åªè¦æ° worker ç便º (origin) åç¶é é¢ç¸åï¼ä¹å¯ä»¥å©ç¨ XMLHttpRequest
å·è¡è¼¸åº/輸å
¥ï¼ä½æ¯ responseXML å channel éå
©å屬æ§çº nullï¼ã
dedicated worker åªè½è¢«ç¢çå®çæªæ¡ååï¼ä¸é¢æåå ä»ç´¹ç°¡å®ç Basic dedicated worker example (run dedicated worker) ç¯ä¾ãéåç¯ä¾æå°å ©åæ¸åéå ¥ worker ç¸ä¹ï¼ç¶å¾åæ¼å端é é¢é¡¯ç¤ºç¸ä¹çµæã
嵿¸¬ Worker åè½çºäºåä¸ç¸å®¹ãé¿å é¯èª¤ï¼æå¥½æ¯ç¢ºä¿ worker åå¨å¾ååç¨ä¹ï¼main.jsï¼ï¼
if (window.Worker) {
...
}
ç¢ç dedicated worker
åªè¦å¼å« Worker()
建æ§åï¼å³å
¥ JS æªæ¡ç URIï¼ä¾¿å¯ä»¥çæä¸å worker å·è¡ç·ï¼main.jsï¼ï¼
var myWorker = new Worker("worker.js");
å dedicated worker ç¼éè¨æ¯
postMessage()
æ¹æ³ä»¥å onmessage
äºä»¶èçå¨å°±æ¯å worker ç¼éè¨æ¯çééµï¼main.jsï¼ï¼
first.onchange = function () {
myWorker.postMessage([first.value, second.value]);
console.log("Message posted to worker");
};
second.onchange = function () {
myWorker.postMessage([first.value, second.value]);
console.log("Message posted to worker");
};
ç¯ä¾ä¸æå
©å <input>
å
ç´ ï¼first å secondï¼ç¶å
ç´ å¼æ¹è®æï¼æåæå©ç¨ postMessage() æ¹æ³å訴 worker æ¹è®çå¼ (ééç¨é£åï¼ä¹å¯ä»¥ç¨å
¶ä»é¡å¥)ã
ç¶å¾å¨ worker 裡æåå¾ onmessage
æ¥æ¶è¨æ¯ï¼worker.jsï¼ï¼
onmessage = function (e) {
console.log("Message received from main script");
var workerResult = "Result: " + e.data[0] * e.data[1];
console.log("Posting message back to main script");
postMessage(workerResult);
};
onmessage
äºä»¶ç©ä»¶ç data 屬æ§åæå³ééä¾çè¨æ¯è³æï¼ä¹å°±æ¯ input å¼ï¼worker æ¶å°å¾å°å³éä¾çå
©åå¼ç¸ä¹ï¼å postMessage å³åå»ã
åå°ä¸»å·è¡ï¼å樣éé onmessage
äºä»¶ï¼æ¶å° worker åå³éä¾çè¨ç®å¼ :
myWorker.onmessage = function (e) {
result.textContent = e.data;
console.log("Message received from worker");
};
æ¿å°åå¨äºä»¶ data ä¸çè¨ç®å¼å¾ï¼æåæ¥èå°å¼ä»¥ textContent
顯示åºä¾ã
åè¨»ï¼ å»ºæ§ Worker
ç URI å¿
é éµå¾same-origin policyãç®ååå®¶ç覽å¨å¨éæ¹é¢åææ§ç°ï¼Gecko 10.0 以å¾å
許 data URI è Internet Explorer 10 ä¸å
許 Blob URIã
åè¨»ï¼ å¨ä¸»å·è¡ç·ä¸åå onmessage
è postMessage
éè¦ä¸»åæå¨ worker ç©ä»¶ä¸ï¼å¨ worker å·è¡ç·åä¸ç¨ï¼éæ¯å çº worker å·è¡ç·çå
¨åç©ä»¶ä¾¿æ¯ worker ç©ä»¶ã
åè¨»ï¼ å worker å³éçè³æä¸¦éå ±äº«èæ¯è¤è£½ä¸ä»½å¾å³éï¼è©³ç´°è«åç § å workers å³éè³æï¼æ´å¤ç´°ç¯ã
çµæ workerå¨ä¸»å·è¡ç·è£¡å¼å« terminate
å°±å¯çµæ worker:
è«æ³¨æä¸è« worker æ£å¨å·è¡çéç®å®æèå¦ï¼ä¸ä½å¼å«å¾ worker 便æç«å»è¢«çµæ¢ã
èå¨ worker å·è¡ç·è£¡ï¼worker å¯ä»¥å¼å«èªå·±ç close
æ¹æ³ä¾çµæ :
ç¶å·è¡ææé¯èª¤ç¼çæï¼onerror äºä»¶èçå¨æè¢«å¼å«ï¼onerror äºä»¶èç卿æ¶å°ä¸åçº error çäºä»¶ç©ä»¶ (å¯¦ä½ ErrorEvent Interface)ï¼è©²äºä»¶ä¸æ bubble ä¸å¯åæ¶ï¼å¦æè¦é¿å
äºä»¶é è¨è¡çºï¼å¯ä»¥å¼å« preventDefault()
ã
以ä¸ä¸åé¨åæ¯é¯èª¤äºä»¶è¼ééµçå°æ¹:
message
ä¾äººé±è®çé¯èª¤è¨æ¯
filename
é¯èª¤ç¼çæå¨çæªæ¡å稱
lineno
é¯èª¤ç¼çæå¨çè¡æ¸
worker å¯ä»¥ç¢çå ¶ä» worker (subworker)ï¼subworker ç便ºä¹å¿ é å主é ç¸åï¼å¦å¤ï¼subworker ç URI çè§£ææ¯ç¸å°æ¼ç¶ worker çä½ç½®èéæå¨é é¢ï¼éé ç¹è²æå©æ¼è¿½è¹¤ worker éçç¸ä¾æ§ã
å¼å ¥ç¨å¼è ³æ¬èå½å¼åº« (library)Worker å·è¡ç·è½ååä¸åå ¨å彿¸ (global function), importScripts()ãimportScripts() å¯ä»¥è® worker 端å¼å ¥ç¸åç¶²åçç¨å¼ç¢¼è ³æ¬è librariesï¼importScripts()坿¥æ¶é¶å°æ¸åè¦è¢«è¼¸å ¥è³æºç URIï¼åºä¸çºå¹¾åç¯ä¾:
importScripts(); /* imports nothing */
importScripts("foo.js"); /* imports just "foo.js" */
importScripts("foo.js", "bar.js"); /* imports two scripts */
çè¦½å¨æè¼å ¥ä¸¦å·è¡æ¯åç¨å¼ç¢¼è ³æ¬ï¼ç¶å¾ worker è½å¤ ååç¨å¼ç¢¼è ³æ¬å §å®ç¾©çå ¨åè®æ¸ï¼è¥æ¯è ³æ¬ç¡æ³è¼å ¥ï¼æç¢çä¸å NETWORK_ERRORï¼å¾çºçç¨å¼ç¢¼ä¸æè¢«å·è¡ï¼ä½æ¯å åå·è¡éçç¨å¼ç¢¼æç¨ window.setTimeout() å»¶é²å·è¡çç¨å¼ç¢¼ä¾ç¶ææï¼è importScripts() ä¹å¾å®£åç彿¸ä¹ä¸æ¨£åå¨ï¼å çºéäºç¨å¼ç¢¼ç¸½æ¯å¨å ¶ä»ç¨å¼ç¢¼ä¹å就解æéäºã
åè¨»ï¼ éç¶ç¨å¼ç¢¼è ³æ¬çä¸è¼é åºä¸ä¸å®ï¼ä½å·è¡é åºæéµç §å³å ¥ importScripts()çé åºï¼éæ¯åæ¥å®æçï¼importScripts()䏿åå³ç´å°ææçç¨å¼ç¢¼é½ä¸è¼ä¸¦å·è¡å®ã
shared worker è½å¤ 被å¤åç¨å¼è ³æ¬ååï¼ç¸±ä½¿è·¨è¶ä¸å windowãiframe æ workerãééç Basic shared worker example (run shared worker) ç¯ä¾å dedicated worker ç¯ä¾é¡ä¼¼ï¼ä½å¤äºå ©åå¯ä»¥è®å¤åæªæ¡ååç彿¸ï¼æ¸åç¸ä¹ä»¥åæ¸åå¹³æ¹ã
è«æ³¨æ dedicated worker è shared worker éçå·®ç°èï¼ç¯ä¾è£¡ææå ©ä»½ HTML é é¢ï¼åèªé½å©ç¨åä¸å worker èçéç®ã
åè¨»ï¼ ææçç覽ç°å¢é½å¿ éå ±äº«ç¸åç便ºï¼ç¸å protocol, host å portï¼ï¼shared worker æè½è®ä¸åç覽ç°å¢ååã
åè¨»ï¼ å¨ Firefoxï¼shared worker ç¡æ³å¨ä¸è¬åé±ç§æ¨¡å¼éå ±äº«ï¼Firefox bug 1177621ï¼ã
å dedicated worker 忳差ä¸å¤ï¼åªæ¯ç¨å¦ä¸å SharedWorker 建æ§åä¾ç¢ç shared workerï¼è¦ index.html å index2.html:
var myWorker = new SharedWorker("worker.js");
ç¸ç¶ä¸ 䏿¨£çæ¯å shared worker æºéå¿ é è¦éé port ç©ä»¶ï¼å ¶å¯¦ dedicated worker 乿¯å¦æ¤ï¼åªä¸éä¸åæ¯å¨èæ¯å¾èªå宿ã
éå port é£ç·ä¸æ¯å¨ onmessage äºä»¶ä¸èæ¯å®æï¼äºæ¯èç±ä¸»åå¼å« start() 好éå§å³éè¨æ¯ãç¯ä¾ multiply.js 以å worker.js å çºè¨»åäº onmessage äºä»¶ï¼æä»¥å
¶å¯¦å¯ä»¥çç¥å¼å« start()ï¼ç¶èè¥æ¯ message äºä»¶æ¯ç¶ç± addEventListener()
註åï¼é£éº¼ä¾¿éè¦å¼å« start() äºã
ç¶ä½¿ç¨ start() éå port é£ç·ï¼é£éº¼éåæºé便éè¦ä¸»å·è¡ç·å worker å ©ç«¯é½å¼å« start()ã
myWorker.port.start(); // called in parent thread
port.start(); // called in worker thread, assuming the port variable references a port
å¦ååé¢ï¼ç¾å¨å¯ä»¥å¼å« postMessage()
ç¼éè¨æ¯ï¼åªä¸é鿬¡éè¦éé port ç©ä»¶ï¼ä¸æ¨£è«åè multiply.js å square.jsï¼ï¼
squareNumber.onchange = function () {
myWorker.port.postMessage([squareNumber.value, squareNumber.value]);
console.log("Message posted to worker");
};
worker æ¹é¢ä¹å¢å äºä¸äºç¨å¼ç¢¼ï¼worker.jsï¼ï¼
onconnect = function (e) {
var port = e.ports[0];
port.onmessage = function (e) {
var workerResult = "Result: " + e.data[0] * e.data[1];
port.postMessage(workerResult);
};
port.start(); // not necessary since onmessage event handler is being used
};
é¦å
ï¼å
ç£è½é£ç·å»ºç«ç onconnect äºä»¶ï¼ä¾å¦ç¶ä¸»å·è¡ç·å»ºç« onmessage äºä»¶æå¼å« start()
ã
ç¶å¾å¾ onconnect äºä»¶ç©ä»¶ï¼æåå¯ä»¥åå¾ port ç©ä»¶ä½¿ç¨ä¹ã
åå¾ port ä¹å¾ï¼æå註å port ä¸ç onmessage äºä»¶ï¼ç¶æè¨æ¯é²ä¾ä¾¿ååè³æé²è¡éç®å¾åå³åå»ï¼è¨»å onmessage äºä»¶çåæä¹èªå建ç«é£ç·ï¼æä»¥èªªä¸éè¦å¼å« start() äºã
æå¾å¨ä¸»å·è¡ç·ç«¯ï¼æå忍£ç± onmessage äºä»¶åååå³éä¾çè¨æ¯ï¼ä¸æ¨£è«åè multiply.js å square.jsï¼ï¼
myWorker.port.onmessage = function (e) {
result2.textContent = e.data[0];
console.log("Message received from worker");
};
å·è¡ç· (Thread) å®å
¨
Worker
æç¢ççæ£ OS 層ç´çå·è¡ç·ï¼ç´°å¿çéç¼è
æè¨±ææå¿åæ¥åé¡ã
ä¸é worker æååæ³¨æåå ¶ä»å·è¡ç·æºéççæ³ï¼ä¸æå»ååéå·è¡ç·å®å ¨çå ä»¶ï¼å¦ DOM ï¼èä¸è³æçå³éä¹é½åºåå (serialized) ï¼æä»¥èªªå¾é£æç¼ç忥åé¡ã
å workers å³éè³æï¼æ´å¤ç´°ç¯å workers å³éçè³ææå 被è¤è£½ä¸ä»½ï¼èéå ±äº«ï¼ç¶éåºååå¾ (serialized) å³è¼¸ï¼ç¶å¾å¨å¦ä¸ç«¯ååºåå (de-serialized) ååºï¼å¤§é¨ä»½çç覽å¨é½æ¯ä»¥ çµæ§åè¤è£½ (structured cloning) 實ä½éé ç¹è².
ä¸é¢ç emulateMessage()
ææ¨¡æ¬å worker å³éè¨æ¯æï¼è¤è£½è³æçè¡çºã
function emulateMessage(vVal) {
return eval("(" + JSON.stringify(vVal) + ")");
}
// Tests
// test #1
var example1 = new Number(3);
console.log(typeof example1); // object
console.log(typeof emulateMessage(example1)); // number
// test #2
var example2 = true;
console.log(typeof example2); // boolean
console.log(typeof emulateMessage(example2)); // boolean
// test #3
var example3 = new String("Hello World");
console.log(typeof example3); // object
console.log(typeof emulateMessage(example3)); // string
// test #4
var example4 = {
name: "John Smith",
age: 43,
};
console.log(typeof example4); // object
console.log(typeof emulateMessage(example4)); // object
// test #5
function Animal(sType, nAge) {
this.type = sType;
this.age = nAge;
}
var example5 = new Animal("Cat", 3);
alert(example5.constructor); // Animal
alert(emulateMessage(example5).constructor); // Object
æè¬çè¨æ¯å°±æ¯ç¶éè¤è£½ãéå
±äº«çè³æï¼å°ééä½ æè©²å·²ç¶ç¥é postMessage()
è² è²¬ç¼éè¨æ¯ï¼ç¶å¾ message
äºä»¶ data
ç attribute ååæå³éçè¨æ¯è³æã
example.html: (the main page):
var myWorker = new Worker("my_task.js");
myWorker.onmessage = function (oEvent) {
console.log("Worker said : " + oEvent.data);
};
myWorker.postMessage("ali");
my_task.js (the worker):
postMessage("I'm working before postMessage('ali').");
onmessage = function (oEvent) {
postMessage("Hi " + oEvent.data);
};
çµæ§åè¤è£½ï¼structured cloningï¼ æ¼ç®æ³æ¯æ´ JSON 以åè¿´ååç §ï¼circular referencesï¼ã
è³æå³éç¯ä¾ ç¯ä¾ 1: é忥eval()
ä¸é¢éé data URL å eval()
ï¼ç¤ºç¯å¦ä½å¨ worker é忥å·è¡å
許çç¨å¼ç¢¼ï¼
// Syntax: asyncEval(code[, listener])
var asyncEval = (function () {
var aListeners = [],
oParser = new Worker(
"data:text/javascript;charset=US-ASCII,onmessage%20%3D%20function%20%28oEvent%29%20%7B%0A%09postMessage%28%7B%0A%09%09%22id%22%3A%20oEvent.data.id%2C%0A%09%09%22evaluated%22%3A%20eval%28oEvent.data.code%29%0A%09%7D%29%3B%0A%7D",
);
oParser.onmessage = function (oEvent) {
if (aListeners[oEvent.data.id]) {
aListeners[oEvent.data.id](oEvent.data.evaluated);
}
delete aListeners[oEvent.data.id];
};
return function (sCode, fListener) {
aListeners.push(fListener || null);
oParser.postMessage({
id: aListeners.length - 1,
code: sCode,
});
};
})();
data URL ç¸ç¶æ¼ç¶²è·¯è«æ±ï¼ç¯ä¾ä¸ç data URL æå¨ worker å·è¡ä¸åç¨å¼ç¢¼åæè¨æ¯ï¼
onmessage = function (oEvent) {
postMessage({
id: oEvent.data.id,
evaluated: eval(oEvent.data.code),
});
};
æç¨ç¯ä¾:
// asynchronous alert message...
asyncEval("3 + 2", function (sMessage) {
alert("3 + 2 = " + sMessage);
});
// asynchronous print message...
asyncEval('"Hello World!!!"', function (sHTML) {
document.body.appendChild(document.createTextNode(sHTML));
});
// asynchronous void...
asyncEval(
'(function () {\n\tvar oReq = new XMLHttpRequest();\n\toReq.open("get", "http://www.mozilla.org/", false);\n\toReq.send(null);\n\treturn oReq.responseText;\n})()',
);
ç¯ä¾ 2: JSON è³æé²éå³éèå¼å«ç³»çµ±
ä¸é¢çç¯ä¾ç³»çµ±é©åéè¦å¨ä¸»é é¢å worker å³éè¤éè³æåå¼å«å¤å彿¸çæ å¢ã
example.html (主é é¢):
<!doctype html>
<html>
<head>
<meta charset="UTF-8" />
<title>MDN Example - Queryable worker</title>
<script type="text/javascript">
/*
QueryableWorker instances methods:
* sendQuery(queryable function name, argument to pass 1, argument to pass 2, etc. etc): calls a Worker's queryable function
* postMessage(string or JSON Data): see Worker.prototype.postMessage()
* terminate(): terminates the Worker
* addListener(name, function): adds a listener
* removeListener(name): removes a listener
QueryableWorker instances properties:
* defaultListener: the default listener executed only when the Worker calls the postMessage() function directly
*/
function QueryableWorker(sURL, fDefListener, fOnError) {
var oInstance = this,
oWorker = new Worker(sURL),
oListeners = {};
this.defaultListener = fDefListener || function () {};
oWorker.onmessage = function (oEvent) {
if (
oEvent.data instanceof Object &&
oEvent.data.hasOwnProperty("vo42t30") &&
oEvent.data.hasOwnProperty("rnb93qh")
) {
oListeners[oEvent.data.vo42t30].apply(
oInstance,
oEvent.data.rnb93qh,
);
} else {
this.defaultListener.call(oInstance, oEvent.data);
}
};
if (fOnError) {
oWorker.onerror = fOnError;
}
this.sendQuery =
function (/* queryable function name, argument to pass 1, argument to pass 2, etc. etc */) {
if (arguments.length < 1) {
throw new TypeError(
"QueryableWorker.sendQuery - not enough arguments",
);
return;
}
oWorker.postMessage({
bk4e1h0: arguments[0],
ktp3fm1: Array.prototype.slice.call(arguments, 1),
});
};
this.postMessage = function (vMsg) {
//I just think there is no need to use call() method
//how about just oWorker.postMessage(vMsg);
//the same situation with terminate
//well,just a little faster,no search up the prototye chain
Worker.prototype.postMessage.call(oWorker, vMsg);
};
this.terminate = function () {
Worker.prototype.terminate.call(oWorker);
};
this.addListener = function (sName, fListener) {
oListeners[sName] = fListener;
};
this.removeListener = function (sName) {
delete oListeners[sName];
};
}
// your custom "queryable" worker
var oMyTask = new QueryableWorker(
"my_task.js" /* , yourDefaultMessageListenerHere [optional], yourErrorListenerHere [optional] */,
);
// your custom "listeners"
oMyTask.addListener("printSomething", function (nResult) {
document
.getElementById("firstLink")
.parentNode.appendChild(
document.createTextNode(" The difference is " + nResult + "!"),
);
});
oMyTask.addListener("alertSomething", function (nDeltaT, sUnit) {
alert("Worker waited for " + nDeltaT + " " + sUnit + " :-)");
});
</script>
</head>
<body>
<ul>
<li>
<a
id="firstLink"
href="javascript:oMyTask.sendQuery('getDifference', 5, 3);"
>What is the difference between 5 and 3?</a
>
</li>
<li>
<a href="javascript:oMyTask.sendQuery('waitSomething');"
>Wait 3 seconds</a
>
</li>
<li>
<a href="javascript:oMyTask.terminate();">terminate() the Worker</a>
</li>
</ul>
</body>
</html>
my_task.js (worker):
// your custom PRIVATE functions
function myPrivateFunc1() {
// do something
}
function myPrivateFunc2() {
// do something
}
// etc. etc.
// your custom PUBLIC functions (i.e. queryable from the main page)
var queryableFunctions = {
// example #1: get the difference between two numbers:
getDifference: function (nMinuend, nSubtrahend) {
reply("printSomething", nMinuend - nSubtrahend);
},
// example #2: wait three seconds
waitSomething: function () {
setTimeout(function () {
reply("alertSomething", 3, "seconds");
}, 3000);
},
};
// system functions
function defaultQuery(vMsg) {
// your default PUBLIC function executed only when main page calls the queryableWorker.postMessage() method directly
// do something
}
function reply(/* listener name, argument to pass 1, argument to pass 2, etc. etc */) {
if (arguments.length < 1) {
throw new TypeError("reply - not enough arguments");
return;
}
postMessage({
vo42t30: arguments[0],
rnb93qh: Array.prototype.slice.call(arguments, 1),
});
}
onmessage = function (oEvent) {
if (
oEvent.data instanceof Object &&
oEvent.data.hasOwnProperty("bk4e1h0") &&
oEvent.data.hasOwnProperty("ktp3fm1")
) {
queryableFunctions[oEvent.data.bk4e1h0].apply(self, oEvent.data.ktp3fm1);
} else {
defaultQuery(oEvent.data);
}
};
ç§»è½è³ææææ¬ - å¯ç§»è½ç©ä»¶ (transferable objects)
Google Chrome 17+ 以å Firefox 18+ è½å¤ å worker 髿è½å°å³éå¦å¤ä¸ç¨®ç¹å®åæ
ç©ä»¶ (å¯ç§»è½ç©ä»¶, transferable objectsï¼é種ç©ä»¶å¯¦ä½äº Transferable
ä»é¢)ï¼å¯ç§»è½ç©ä»¶ç¶è¢«å³éå°å¦ä¸ç«¯æä¸¦ä¸éè¦è¤è£½ï¼å æ¤å¯ä»¥å¤§å¤§æåå³é大åè³æç©ä»¶çæè½ï¼é好æ¯åæ¯ C/C++ ç pass-by-referenceï¼ä½æ¯ä¸åçæ¯ï¼ä¸æ¦ç§»è½å¾åå
çç°å¢ä¾¿å¤±å»äºææè³æï¼ä¾å¦ç¶ä¸»é é¢å³é ArrayBuffer
å¾ï¼ä¸»é é¢ä¾¿ä¸åè½å¤ 使ç¨éçè³æç©ä»¶äºï¼éçè³æç©ä»¶çååé£çµå·²ç¶ééå°ç§»è½å° worker 端äºã
// Create a 32MB "file" and fill it.
var uInt8Array = new Uint8Array(1024 * 1024 * 32); // 32MB
for (var i = 0; i < uInt8Array.length; ++i) {
uInt8Array[i] = i;
}
worker.postMessage(uInt8Array.buffer, [uInt8Array.buffer]);
åè¨»ï¼ éæ¼æ´å¤å¯ç§»è½ç©ä»¶çè³è¨, æè½ååè½åµæ¸¬ï¼è«åè HTML5 Rocks ä¸ Transferable Objects: Lightning Fast! 䏿ã
Embedded workersä¸å <script>
ï¼ä¸¦æ²æä¸å¥æ£å¼æ¨æºçæ¹æ³å° worker çç¨å¼ç¢¼åµå
¥å°é é¢ä¹ä¸ï¼ä¸éæ²æ src 屬æ§èä¸ mime-type ä¸å±¬æ¼å¯å·è¡ç¨å¼ç¢¼ç <script>
å
ç´ æè¢«è¦çº javascript å¯ä»¥åç¨çè³æåå¡ï¼data blockï¼ï¼è³æå塿¯ä¸é
HTML5 å¯ç¨æ¼æå¸¶æåè³æçç¹è²åè½ï¼å©ç¨è³æå塿åå°±æè¾¦æ³åµå
¥ worker çç¨å¼ç¢¼å°é é¢ä¸ï¼
<!doctype html>
<html>
<head>
<meta charset="UTF-8" />
<title>MDN Example - Embedded worker</title>
<script type="text/js-worker">
// This script WON'T be parsed by JS engines because its mime-type is text/js-worker.
var myVar = "Hello World!";
// Rest of your worker code goes here.
</script>
<script type="text/javascript">
// This script WILL be parsed by JS engines because its mime-type is text/javascript.
function pageLog(sMsg) {
// Use a fragment: browser will only render/reflow once.
var oFragm = document.createDocumentFragment();
oFragm.appendChild(document.createTextNode(sMsg));
oFragm.appendChild(document.createElement("br"));
document.querySelector("#logDisplay").appendChild(oFragm);
}
</script>
<script type="text/js-worker">
// This script WON'T be parsed by JS engines because its mime-type is text/js-worker.
onmessage = function (oEvent) {
postMessage(myVar);
};
// Rest of your worker code goes here.
</script>
<script type="text/javascript">
// This script WILL be parsed by JS engines because its mime-type is text/javascript.
// In the past...:
// blob builder existed
// ...but now we use Blob...:
var blob = new Blob(
Array.prototype.map.call(
document.querySelectorAll('script[type="text\/js-worker"]'),
function (oScript) {
return oScript.textContent;
},
),
{ type: "text/javascript" },
);
// Creating a new document.worker property containing all our "text/js-worker" scripts.
document.worker = new Worker(window.URL.createObjectURL(blob));
document.worker.onmessage = function (oEvent) {
pageLog("Received: " + oEvent.data);
};
// Start the worker.
window.onload = function () {
document.worker.postMessage("");
};
</script>
</head>
<body>
<div id="logDisplay"></div>
</body>
</html>
Embedded worker å¨ document.worker
ä¹ä¸ã
ä¸é¢ä»ç´¹å ¶ä»ä½¿ç¨ worker çç¯ä¾ã
å¨èæ¯ä¸å·è¡éç®worker 主è¦çç¨èå¨é¿å é度 CPU éç®çä»»åé»ç¤å° UI å·è¡ç·éè¡ï¼ééæåç¨ worker ä¾è· Fibonacci æ¸åéç®ã
JavaScriptfibonacci.js ä¸çç¨å¼ç¢¼æè¢«å¦ä¸ä»½ HTML å¼ç¨ã
var results = [];
function resultReceiver(event) {
results.push(parseInt(event.data));
if (results.length == 2) {
postMessage(results[0] + results[1]);
}
}
function errorReceiver(event) {
throw event.data;
}
onmessage = function (event) {
var n = parseInt(event.data);
if (n == 0 || n == 1) {
postMessage(n);
return;
}
for (var i = 1; i <= 2; i++) {
var worker = new Worker("fibonacci.js");
worker.onmessage = resultReceiver;
worker.onerror = errorReceiver;
worker.postMessage(n - i);
}
};
worker ç¨å¼ç¢¼ä¸è¨»åäºä¸å onmessage
äºä»¶èçå¨ç¨ä¾æ¥æ¶å¦ä¸ç«¯ postMessage éä¾çè¨æ¯
(è«æ³¨æé並éå®ç¾©ä¸åå
¨åè®æ¸æå½æ¸ï¼var onmessage
æ function onmessage
æå®ç¾©å
¨åè®æ¸ï¼ä½ä¸æè¨»åäºä»¶èçå¨)ï¼ç¶å¾éå§é²è¡éè¿´éç®ã
<!doctype html>
<html>
<head>
<meta charset="UTF-8" />
<title>Test threads fibonacci</title>
</head>
<body>
<div id="result"></div>
<script language="javascript">
var worker = new Worker("fibonacci.js");
worker.onmessage = function (event) {
document.getElementById("result").textContent = event.data;
dump("Got: " + event.data + "\n");
};
worker.onerror = function (error) {
dump("Worker error: " + error.message + "\n");
throw error;
};
worker.postMessage("5");
</script>
</body>
</html>
onmessage äºä»¶èçå¨ææ¥æ¶ worker åå³çéç®çµæï¼ç¶å¾é¡¯ç¤ºå¨é é¢ä¸ï¼å¦ææåé¡ï¼ onerror äºä»¶èç卿 è¼¸åº é¯èª¤è¨æ¯ã
å worker æºé忝å©ç¨ postMessageã
ç¯ä¾æ¸¬è©¦ã
å¨èæ¯ä¸å·è¡ web I/Oç¯ä¾è«è¦ Using workers in extensions ã
åå²ä»»åå°å¤å workersåºæ¼å¤æ ¸ cpu çæ®åï¼åå²è¤éä»»åå°å¤å workers å°å¯è½æå©æ¼å©ç¨å¤æ ¸å¿ cpu çåªå¢ã
å ¶ä»é¡åç workeré¤äº dedicated å shared web workersï¼éæå ¶ä»ç¨®é¡ï¼
ChromeWorker
ã大夿¸ Javascript çåè½ worker çå¯ä»¥ä½¿ç¨ï¼å å«ï¼
Navigator
fetch()
Array
ãDate
ãMath
è String
setTimeout()
è setInterval()
worker ç¡æ³æä½ä¸»é é¢çç©ä»¶è DOMï¼å¦æç¸ééæ±ï¼å¿
é è¦éæ¥éé DedicatedWorkerGlobalScope.postMessage
éç¥ä¸»é é¢ï¼è®ä¸»é é¢å·è¡éæ±ã
åè¨»ï¼ ææ worker å¯åååè½ä¸è¦½è¡¨ï¼è«è¦ Functions and interfaces available to workers.
è¦ç¯ åè¦RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4