ปัญหา: การเกิดขึ้นพร้อมกันของ JavaScript
มีปัญหาคอขวดจำนวนมากที่ขัดขวางไม่ให้ระบบย้ายแอปพลิเคชันที่น่าสนใจ (เช่น จากการติดตั้งใช้งานจำนวนมากของเซิร์ฟเวอร์) ไปยัง JavaScript ฝั่งไคลเอ็นต์ เช่น ความเข้ากันได้ของเบราว์เซอร์ การพิมพ์แบบคงที่ การช่วยเหลือพิเศษ และประสิทธิภาพ แต่ในทางกลับกัน ผู้ให้บริการเบราว์เซอร์ก็พัฒนาความเร็วของเครื่องมือ JavaScript ของตนได้อย่างรวดเร็ว
สิ่งหนึ่งที่ยังคงเป็นอุปสรรคสำหรับ JavaScript ก็คือตัวภาษาเอง JavaScript เป็นสภาพแวดล้อมแบบเทรดเดียว ซึ่งหมายความว่าสคริปต์หลายรายการจะทำงานพร้อมกันไม่ได้ ตัวอย่างเช่น สมมติว่ามีเว็บไซต์ที่ต้องจัดการเหตุการณ์ UI, ค้นหาและประมวลผลข้อมูล API จำนวนมาก และดัดแปลง DOM ค่อนข้างเหมือนกันใช่ไหม อย่างไรก็ตาม ทั้ง 2 อย่างนี้ไม่สามารถเกิดขึ้นพร้อมกันเนื่องจากข้อจำกัดในรันไทม์ JavaScript ของเบราว์เซอร์ การเรียกใช้สคริปต์จะเกิดขึ้นภายในเทรดเดียว
นักพัฒนาซอฟต์แวร์จะเลียนแบบ "การเกิดขึ้นพร้อมกัน" โดยใช้เทคนิคต่างๆ เช่น setTimeout()
, setInterval()
, XMLHttpRequest
และเครื่องจัดการเหตุการณ์
ได้ ฟีเจอร์ทั้งหมดนี้ทำงานแบบไม่พร้อมกัน แต่การไม่บล็อกไม่ได้หมายถึงการเกิดขึ้นพร้อมกัน
ระบบจะประมวลผลเหตุการณ์ที่ไม่พร้อมกันหลังจากแสดงผลสคริปต์ที่เรียกใช้ปัจจุบันแล้ว ข่าวดีก็คือ HTML5 ให้บางอย่างที่ดีกว่าการแฮ็กเหล่านี้!
ขอแนะนำ Web Workers: นำชุดข้อความไปยัง JavaScript
ข้อกำหนดของ Web Workers กำหนด API สำหรับการวางสคริปต์พื้นหลังในเว็บแอปพลิเคชันของคุณ Web Workers ให้คุณทำสิ่งต่างๆ ได้ เช่น เริ่มการทำงานของสคริปต์ที่ใช้เวลานานเพื่อจัดการงานที่เน้นการคำนวณ แต่ไม่บล็อก UI หรือสคริปต์อื่นๆ เพื่อจัดการการโต้ตอบของผู้ใช้ พวกเขาจะช่วยหยุดกล่องโต้ตอบ "สคริปต์ไม่ตอบสนอง" ที่น่ารังเกียจ ที่เราทุกคนชื่นชอบ:
ผู้ปฏิบัติงานใช้การส่งผ่านข้อความที่มีลักษณะคล้ายชุดข้อความเพื่อให้การทำงานพร้อมกัน ซึ่งเหมาะสำหรับการทำให้ UI รีเฟรช มีประสิทธิภาพ และตอบสนองผู้ใช้อยู่เสมอ
ประเภทของ Web Worker
โปรดทราบว่าข้อกำหนดได้กล่าวถึง Web Worker 2 ประเภท ได้แก่ Dedicated Worker และ Shared Workers บทความนี้จะกล่าวถึง ผู้ปฏิบัติงานเฉพาะทางเท่านั้น เราจะเรียกลูกค้าเหล่านี้ว่า "เว็บผู้ปฏิบัติงาน" หรือ "ผู้ปฏิบัติงาน"
เริ่มต้นใช้งาน
Web Worker จะทำงานในเทรดที่แยกต่างหาก ดังนั้น โค้ดที่เรียกใช้จะต้องอยู่ในไฟล์แยกต่างหาก
แต่ก่อนที่จะดำเนินการดังกล่าว สิ่งแรกที่ต้องทำคือสร้างออบเจ็กต์ Worker
ใหม่ในหน้าหลัก ตัวสร้างจะใช้ชื่อสคริปต์ผู้ปฏิบัติงาน:
var worker = new Worker('task.js');
หากมีไฟล์ที่ระบุ เบราว์เซอร์จะสร้างเทรดผู้ปฏิบัติงานใหม่ ซึ่งจะดาวน์โหลดแบบไม่พร้อมกัน ผู้ปฏิบัติงานจะไม่เริ่มทํางานจนกว่าไฟล์จะดาวน์โหลดและเรียกใช้เสร็จสมบูรณ์ หากเส้นทางไปยังผู้ปฏิบัติงานแสดงข้อผิดพลาด 404 ผู้ปฏิบัติงานจะล้มเหลวโดยไม่มีการแจ้งเตือน
หลังจากสร้างผู้ปฏิบัติงานแล้ว ให้เริ่มต้นโดยเรียกใช้เมธอด postMessage()
:
worker.postMessage(); // Start the worker.
การสื่อสารกับผู้ปฏิบัติงานผ่านทางข้อความ
การสื่อสารระหว่างงานและหน้าหลักจะดำเนินการโดยใช้โมเดลเหตุการณ์และเมธอด postMessage()
postMessage()
จะยอมรับสตริงหรือออบเจ็กต์ JSON เป็นอาร์กิวเมนต์เดียวก็ได้ ทั้งนี้ขึ้นอยู่กับเบราว์เซอร์/เวอร์ชัน
เวอร์ชันล่าสุดของเบราว์เซอร์สมัยใหม่รองรับการส่งออบเจ็กต์ JSON
ด้านล่างนี้เป็นตัวอย่างการใช้สตริงเพื่อส่ง " Hello World" ไปยังผู้ปฏิบัติงานใน doWork.js ผู้ปฏิบัติงานจะส่งคืน ข้อความที่ส่งมาให้
สคริปต์หลัก:
var worker = new Worker('doWork.js');
worker.addEventListener('message', function(e) {
console.log('Worker said: ', e.data);
}, false);
worker.postMessage('Hello World'); // Send data to our worker.
doWork.js (ผู้ปฏิบัติงาน):
self.addEventListener('message', function(e) {
self.postMessage(e.data);
}, false);
เมื่อมีการเรียกใช้ postMessage()
จากหน้าหลัก ผู้ปฏิบัติงานของเราจะจัดการข้อความนั้นโดยการกำหนดตัวแฮนเดิล onmessage
สำหรับเหตุการณ์ message
เพย์โหลดของข้อความ (ในกรณีนี้คือ "สวัสดีโลก") จะเข้าถึงได้ใน Event.data
แม้ว่าตัวอย่างนี้จะไม่น่าตื่นเต้นมากนัก แต่ก็แสดงให้เห็นว่า postMessage()
เป็นวิธีในการส่งข้อมูลกลับไปยังเทรดหลักด้วย สะดวก
ระบบจะไม่คัดลอกข้อความที่ส่งระหว่างหน้าหลักและผู้ปฏิบัติงาน เช่น ในตัวอย่างถัดไป คุณเข้าถึงคุณสมบัติ "msg" ของข้อความ JSON ได้จากทั้ง 2 ตำแหน่ง ดูเหมือนว่าออบเจ็กต์จะส่งผ่านไปยังผู้ปฏิบัติงานโดยตรง แม้ว่าวัตถุจะทำงานในพื้นที่เฉพาะที่แยกต่างหาก ในความเป็นจริง สิ่งที่เกิดขึ้นคือวัตถุกำลังถูกทำให้เป็นอนุกรมขณะส่งไปให้ผู้ปฏิบัติงาน แล้วก็ยกเลิกการซีเรียลที่อีกฝั่งหนึ่ง หน้าเว็บและผู้ปฏิบัติงานไม่ได้แชร์อินสแตนซ์เดียวกัน ดังนั้นผลลัพธ์สุดท้ายคือระบบจึงสร้างข้อมูลที่ซ้ำกันในแต่ละบัตรผ่าน เบราว์เซอร์ส่วนใหญ่ใช้ฟีเจอร์นี้โดยการเข้ารหัส/ถอดรหัส JSON โดยอัตโนมัติทั้ง 2 ฝั่ง
ต่อไปนี้เป็นตัวอย่างที่ซับซ้อนยิ่งขึ้นซึ่งส่งข้อความโดยใช้ออบเจ็กต์ JSON
สคริปต์หลัก:
<button onclick="sayHI()">Say HI</button>
<button onclick="unknownCmd()">Send unknown command</button>
<button onclick="stop()">Stop worker</button>
<output id="result"></output>
<script>
function sayHI() {
worker.postMessage({'cmd': 'start', 'msg': 'Hi'});
}
function stop() {
// worker.terminate() from this script would also stop the worker.
worker.postMessage({'cmd': 'stop', 'msg': 'Bye'});
}
function unknownCmd() {
worker.postMessage({'cmd': 'foobard', 'msg': '???'});
}
var worker = new Worker('doWork2.js');
worker.addEventListener('message', function(e) {
document.getElementById('result').textContent = e.data;
}, false);
</script>
doWork2.js:
self.addEventListener('message', function(e) {
var data = e.data;
switch (data.cmd) {
case 'start':
self.postMessage('WORKER STARTED: ' + data.msg);
break;
case 'stop':
self.postMessage('WORKER STOPPED: ' + data.msg +
'. (buttons will no longer work)');
self.close(); // Terminates the worker.
break;
default:
self.postMessage('Unknown command: ' + data.msg);
};
}, false);
ออบเจ็กต์ที่โอนได้
เบราว์เซอร์ส่วนใหญ่ใช้อัลกอริทึมการโคลนโครงสร้าง ซึ่งช่วยให้คุณส่งประเภทที่ซับซ้อนมากขึ้นเข้า/ออกจาก Worker เช่น File
, Blob
, ArrayBuffer
และออบเจ็กต์ JSON อย่างไรก็ตาม เมื่อส่งข้อมูลประเภทเหล่านี้โดยใช้ postMessage()
ระบบจะยังคงทำสำเนาไว้ ดังนั้น หากกำลังส่งไฟล์ขนาดใหญ่ 50 MB (เช่น) จะมีค่าใช้จ่ายที่เห็นได้ชัดในการรับไฟล์นั้นระหว่างผู้ปฏิบัติงานกับเทรดหลัก
การโคลนที่มีโครงสร้างนั้นเป็นเรื่องดี แต่การคัดลอกอาจใช้เวลาหลายร้อยมิลลิวินาที คุณใช้ออบเจ็กต์ที่โอนได้เพื่อต่อสู้กับการโจมตี Perf ได้
เมื่อใช้ออบเจ็กต์ที่โอนได้ ระบบจะโอนข้อมูลจากบริบทหนึ่งไปยังอีกบริบทหนึ่ง เอกสารนี้จะทำงานได้ไม่มีสำเนา ซึ่งช่วยปรับปรุงประสิทธิภาพในการส่งข้อมูลไปยังผู้ปฏิบัติงานได้เป็นอย่างมาก หากคุณมาจากกลุ่ม C/C++ ให้คิดว่านี่เป็นการอ้างอิง อย่างไรก็ตาม "เวอร์ชัน" จากบริบทการโทรจะใช้งานไม่ได้อีกต่อไปเมื่อโอนไปยังบริบทใหม่ ซึ่งต่างจากการอ้างอิงแบบอ้างอิง ตัวอย่างเช่น เมื่อโอน ArrayBuffer จากแอปหลักของคุณไปยัง Worker ระบบจะล้าง ArrayBuffer
เดิมและจะใช้งานไม่ได้อีกต่อไป โดยระบบจะโอนเนื้อหาของไฟล์ไปยังบริบทของผู้ปฏิบัติงาน (โดยเงียบๆ)
หากต้องการใช้ออบเจ็กต์ที่โอนได้ ให้ใช้ลายเซ็นของ postMessage()
ที่ต่างออกไปเล็กน้อย ดังนี้
worker.postMessage(arrayBuffer, [arrayBuffer]);
window.postMessage(arrayBuffer, targetOrigin, [arrayBuffer]);
กรณีของผู้ปฏิบัติงาน อาร์กิวเมนต์แรกคือข้อมูล และอาร์กิวเมนต์ที่ 2 คือลิสต์รายการที่ควรโอน อาร์กิวเมนต์แรกไม่จำเป็นต้องเป็น ArrayBuffer
เช่น อาจเป็นออบเจ็กต์ JSON
worker.postMessage({data: int8View, moreData: anotherBuffer},
[int8View.buffer, anotherBuffer]);
ประเด็นสําคัญ: อาร์กิวเมนต์ที่ 2 ต้องเป็นอาร์เรย์ของ ArrayBuffer
นี่คือรายการรายการที่โอนได้ของคุณ
ดูข้อมูลเพิ่มเติมเกี่ยวกับการโอนได้ที่โพสต์ของเราที่ developer.chrome.com
สภาพแวดล้อมของผู้ปฏิบัติงาน
ขอบเขตของผู้ปฏิบัติงาน
ในบริบทของผู้ปฏิบัติงาน ทั้ง self
และ this
จะอ้างอิงขอบเขตรวมสำหรับผู้ปฏิบัติงาน ดังนั้น ตัวอย่างก่อนหน้านี้อาจเขียนเป็น
addEventListener('message', function(e) {
var data = e.data;
switch (data.cmd) {
case 'start':
postMessage('WORKER STARTED: ' + data.msg);
break;
case 'stop':
...
}, false);
หรือคุณสามารถตั้งค่าเครื่องจัดการเหตุการณ์ onmessage
โดยตรง
(แม้ว่านินจา JavaScript จะสนับสนุน addEventListener
เสมอ)
onmessage = function(e) {
var data = e.data;
...
};
ฟีเจอร์ที่ผู้ปฏิบัติงานใช้ได้
เนื่องจากลักษณะการทำงานแบบมัลติเทรด Web Workers จึงมีสิทธิ์เข้าถึงฟีเจอร์ของ JavaScript เพียงบางส่วนเท่านั้น ดังนี้
- ออบเจ็กต์
navigator
- ออบเจ็กต์
location
(อ่านอย่างเดียว) XMLHttpRequest
setTimeout()/clearTimeout()
และsetInterval()/clearInterval()
- แคชของแอปพลิเคชัน
- การนำเข้าสคริปต์ภายนอกโดยใช้เมธอด
importScripts()
- กำลังสร้าง Web Worker อื่นๆ
ผู้ปฏิบัติงานไม่มีสิทธิ์เข้าถึงสิ่งต่อไปนี้
- DOM (ไม่ปลอดภัยต่อชุดข้อความ)
- ออบเจ็กต์
window
- ออบเจ็กต์
document
- ออบเจ็กต์
parent
กำลังโหลดสคริปต์ภายนอก
คุณโหลดไฟล์สคริปต์ภายนอกหรือไลบรารีลงในผู้ปฏิบัติงานด้วยฟังก์ชัน importScripts()
ได้ เมธอดนี้ไม่ใช้สตริงตั้งแต่ 0 สตริงขึ้นไปแทนชื่อไฟล์ของทรัพยากรที่จะนำเข้า
ตัวอย่างนี้โหลด script1.js
และ script2.js
ลงในผู้ปฏิบัติงาน
worker.js:
importScripts('script1.js');
importScripts('script2.js');
ซึ่งสามารถเขียนเป็นคำสั่งนำเข้ารายการเดียวก็ได้
importScripts('script1.js', 'script2.js');
ผู้ปฏิบัติงานย่อย
ผู้ปฏิบัติงานสามารถตั้งถิ่นฐานของผู้ปฏิบัติงานเด็กได้ เหมาะอย่างยิ่งสำหรับการแบ่งงาน ขนาดใหญ่ๆ ขณะรันไทม์ อย่างไรก็ตาม คนทำงานย่อยอาจมีข้อควรระวังบางประการดังนี้
- ผู้ปฏิบัติงานย่อยต้องโฮสต์ภายในต้นทางเดียวกับหน้าหลัก
- URI ภายในงานย่อยจะได้รับการแก้ไขโดยสัมพันธ์กับตำแหน่งของผู้ปฏิบัติงานหลัก (แทนที่จะเป็นหน้าหลัก)
โปรดทราบว่าเบราว์เซอร์ส่วนใหญ่สร้างกระบวนการแยกกันสำหรับผู้ปฏิบัติงานแต่ละคน ก่อนจะเริ่มสร้างฟาร์มคนงาน ให้ระวังการใช้ทรัพยากรระบบของผู้ใช้มากเกินไป เหตุผลหนึ่งก็คือระบบจะคัดลอก ข้อความที่ส่งต่อระหว่างหน้าหลักและผู้ปฏิบัติงานไว้โดยไม่แชร์ ดูการสื่อสารกับผู้ปฏิบัติงานผ่านการส่งข้อความ
ดูตัวอย่างวิธีสร้างผู้ปฏิบัติงานย่อยได้จากตัวอย่างในข้อกำหนด
ผู้ปฏิบัติงานในบรรทัด
ถ้าคุณต้องการสร้างสคริปต์สำหรับผู้ปฏิบัติงานทันที หรือสร้างหน้าเว็บที่ทำงานได้ด้วยตัวเอง
โดยไม่ต้องสร้างไฟล์ผู้ปฏิบัติงานแยกต่างหาก เมื่อใช้ Blob()
คุณจะ "แทรก" ผู้ปฏิบัติงานในหน้าในไฟล์ HTML เดียวกันกับตรรกะหลักได้โดยสร้างแฮนเดิล URL ให้โค้ดผู้ปฏิบัติงานเป็นสตริง ดังนี้
var blob = new Blob([
"onmessage = function(e) { postMessage('msg from worker'); }"]);
// Obtain a blob URL reference to our worker 'file'.
var blobURL = window.URL.createObjectURL(blob);
var worker = new Worker(blobURL);
worker.onmessage = function(e) {
// e.data == 'msg from worker'
};
worker.postMessage(); // Start the worker.
URL ของ Blob
สิ่งมหัศจรรย์มาพร้อมกับการโทรหา window.URL.createObjectURL()
วิธีนี้จะสร้างสตริง URL แบบง่ายที่ใช้เพื่ออ้างอิงข้อมูลที่จัดเก็บไว้ในออบเจ็กต์ DOM File
หรือ Blob
ได้ เช่น
blob:http://localhost/c745ef73-ece9-46da-8f66-ebes574789b1
URL ของ Blob จะไม่ซ้ำกันและมีอายุการใช้งานของแอปพลิเคชัน (เช่น จนกว่า document
จะถูกยกเลิกการโหลด) ถ้าคุณสร้าง URL ของ Blob จำนวนมาก คุณควรเผยแพร่การอ้างอิงที่ไม่จำเป็นอีกต่อไป คุณสามารถเผยแพร่ URL ของ Blob อย่างชัดแจ้งโดยส่งต่อไปยัง window.URL.revokeObjectURL()
:
window.URL.revokeObjectURL(blobURL);
ใน Chrome จะมีหน้าที่ดีสำหรับดู URL ของ Blob ที่สร้างขึ้นทั้งหมด: chrome://blob-internals/
ตัวอย่างแบบเต็ม
การดำเนินการเพิ่มเติมอีกขั้นทำให้เราเข้าใจวิธีแทรกโค้ด JS ของผู้ปฏิบัติงานในหน้าเว็บ เทคนิคนี้ใช้แท็ก <script>
เพื่อกำหนดผู้ปฏิบัติงาน
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
</head>
<body>
<div id="log"></div>
<script id="worker1" type="javascript/worker">
// This script won't be parsed by JS engines
// because its type is javascript/worker.
self.onmessage = function(e) {
self.postMessage('msg from worker');
};
// Rest of your worker code goes here.
</script>
<script>
function log(msg) {
// Use a fragment: browser will only render/reflow once.
var fragment = document.createDocumentFragment();
fragment.appendChild(document.createTextNode(msg));
fragment.appendChild(document.createElement('br'));
document.querySelector("#log").appendChild(fragment);
}
var blob = new Blob([document.querySelector('#worker1').textContent]);
var worker = new Worker(window.URL.createObjectURL(blob));
worker.onmessage = function(e) {
log("Received: " + e.data);
}
worker.postMessage(); // Start the worker.
</script>
</body>
</html>
ในความคิดของผม วิธีการใหม่นี้ดูสะอาดตาขึ้นและอ่านออกได้ง่ายขึ้น
ซึ่งจะกำหนดแท็กสคริปต์ด้วย id="worker1"
และ type='javascript/worker'
(ดังนั้นเบราว์เซอร์จึงไม่แยกวิเคราะห์ JS) ระบบจะแยกโค้ดดังกล่าวเป็นสตริงโดยใช้ document.querySelector('#worker1').textContent
และส่งไปยัง Blob()
เพื่อสร้างไฟล์
กำลังโหลดสคริปต์ภายนอก
เมื่อใช้เทคนิคเหล่านี้ในการแทรกโค้ดผู้ปฏิบัติงาน importScripts()
จะทำงานก็ต่อเมื่อคุณระบุ URI สัมบูรณ์เท่านั้น หากคุณพยายามส่ง URI แบบสัมพัทธ์ เบราว์เซอร์จะร้องเรียนเกี่ยวกับข้อผิดพลาดด้านความปลอดภัย สาเหตุ: ผู้ปฏิบัติงาน (ตอนนี้สร้างขึ้นจาก BLOB URL) จะได้รับการแก้ไขด้วยคำนำหน้า blob:
ในขณะที่แอปของคุณจะทำงานจากรูปแบบอื่น (น่าจะเป็น http://
) ดังนั้น การดำเนินการไม่สำเร็จจึงเกิดจากข้อจำกัดแบบข้ามต้นทาง
วิธีหนึ่งในการใช้ importScripts()
ในตัวผู้ปฏิบัติงานในหน้าคือการ "แทรก" URL ปัจจุบันของสคริปต์หลักที่เรียกใช้โดยส่ง URL ดังกล่าวไปยังผู้ปฏิบัติงานในหน้าและสร้าง URL ที่สมบูรณ์ด้วยตนเอง ซึ่งจะช่วยให้มั่นใจว่าระบบนำเข้าสคริปต์ภายนอกมาจากต้นทางเดียวกัน สมมติว่าแอปหลักของคุณทำงานจาก http://example.com/index.html
:
...
<script id="worker2" type="javascript/worker">
self.onmessage = function(e) {
var data = e.data;
if (data.url) {
var url = data.url.href;
var index = url.indexOf('index.html');
if (index != -1) {
url = url.substring(0, index);
}
importScripts(url + 'engine.js');
}
...
};
</script>
<script>
var worker = new Worker(window.URL.createObjectURL(bb.getBlob()));
worker.postMessage(<b>{url: document.location}</b>);
</script>
การจัดการข้อผิดพลาด
เช่นเดียวกับตรรกะ JavaScript คุณจะต้องจัดการข้อผิดพลาดใดๆ ที่มีในการทำงานของเว็บผู้ปฏิบัติงาน
หากเกิดข้อผิดพลาดขณะที่ผู้ปฏิบัติงานกำลังดำเนินการ ErrorEvent
จะเริ่มทำงาน อินเทอร์เฟซนี้มีพร็อพเพอร์ตี้ที่เป็นประโยชน์ 3 รายการในการระบุข้อผิดพลาด ได้แก่ filename
ได้แก่ ชื่อสคริปต์ผู้ปฏิบัติงานที่ทำให้เกิดข้อผิดพลาด lineno
คือหมายเลขบรรทัดที่เกิดข้อผิดพลาด และ message
ซึ่งเป็นคำอธิบายข้อผิดพลาดที่สื่อความหมาย นี่คือตัวอย่างการตั้งค่าเครื่องจัดการเหตุการณ์ onerror
เพื่อพิมพ์คุณสมบัติของข้อผิดพลาด
<output id="error" style="color: red;"></output>
<output id="result"></output>
<script>
function onError(e) {
document.getElementById('error').textContent = [
'ERROR: Line ', e.lineno, ' in ', e.filename, ': ', e.message
].join('');
}
function onMsg(e) {
document.getElementById('result').textContent = e.data;
}
var worker = new Worker('workerWithError.js');
worker.addEventListener('message', onMsg, false);
worker.addEventListener('error', onError, false);
worker.postMessage(); // Start worker without a message.
</script>
ตัวอย่าง: WorkerWithError.js พยายามดำเนินการ 1/x โดยที่ไม่มีการกำหนด x
// สิ่งที่ต้องทำ: DevSite - ตัวอย่างโค้ดถูกนำออกเนื่องจากใช้เครื่องจัดการเหตุการณ์แบบอินไลน์
workerWithError.js:
self.addEventListener('message', function(e) {
postMessage(1/x); // Intentional error.
};
คำแนะนำเกี่ยวกับความปลอดภัย
ข้อจำกัดเกี่ยวกับการเข้าถึงในเครื่อง
เนื่องจากข้อจำกัดด้านความปลอดภัยของ Google Chrome ผู้ปฏิบัติงานจะไม่ทำงานเฉพาะที่ (เช่น จาก file://
) ในเบราว์เซอร์เวอร์ชันล่าสุด แต่กลับล้มเหลวโดยไม่มีการแจ้งเตือน หากต้องการเรียกใช้แอปจากรูปแบบ file://
ให้เรียกใช้ Chrome ด้วยการตั้งค่าแฟล็ก --allow-file-access-from-files
เบราว์เซอร์อื่นมีข้อจำกัดเดียวกัน
การพิจารณาที่มาจากแหล่งเดียวกัน
สคริปต์ของผู้ปฏิบัติงานต้องเป็นไฟล์ภายนอกที่มีรูปแบบเหมือนกับหน้าการเรียกใช้ ดังนั้น คุณจึงโหลดสคริปต์จาก URL ของ data:
หรือ URL javascript:
ไม่ได้ และหน้า https:
จะเริ่มสคริปต์สำหรับผู้ปฏิบัติงานที่ขึ้นต้นด้วย http:
URL ไม่ได้
Use Case
แล้วแอปประเภทใดที่จะใช้ Web Worker แนวคิดเพิ่มเติมบางส่วนที่จะช่วยให้สมองของคุณทำงานมีดังนี้
- การดึงข้อมูลล่วงหน้าและ/หรือการแคชข้อมูลไว้ใช้ในภายหลัง
- การไฮไลต์ไวยากรณ์โค้ดหรือการจัดรูปแบบข้อความแบบเรียลไทม์อื่นๆ
- โปรแกรมตรวจตัวสะกด
- กำลังวิเคราะห์ข้อมูลวิดีโอหรือเสียง
- I/O ในเบื้องหลังหรือการสำรวจบริการบนเว็บ
- การประมวลผลอาร์เรย์ขนาดใหญ่หรือการตอบสนอง JSON ที่ตลกขบขัน
- การกรองรูปภาพใน
<canvas>
- กำลังอัปเดตฐานข้อมูลเว็บในเครื่องหลายแถว
ดูข้อมูลเพิ่มเติมเกี่ยวกับกรณีการใช้งานที่เกี่ยวข้องกับ Web Workers API ได้ที่ภาพรวมผู้ปฏิบัติงาน
เดโม
รายการอ้างอิง
- ข้อกำหนดของ Web Workers
- "การใช้ Web Worker" จาก Mozilla Developer Network Web Docs
- "Web Workers ลุกขึ้น!" จาก Dev.Opera