Web Worker เป็นโซลูชันจาวาสคริปต์แบบมัลติเธรดที่จัดทำโดย HTML5 เราสามารถส่งมอบโค้ดที่เน้นการประมวลผลบางส่วนให้กับผู้ปฏิบัติงานบนเว็บเพื่อให้ทำงานโดยไม่ค้างอินเทอร์เฟซผู้ใช้
1: วิธีใช้งานผู้ปฏิบัติงานหลักการพื้นฐานของ Web Worker คือการใช้คลาส Worker เพื่อโหลดไฟล์ JavaScript ในเธรดหลักปัจจุบันของ JavaScript เพื่อเปิดเธรดใหม่ ซึ่งมีผลในการดำเนินการแบบไม่บล็อก และจัดให้มีอินเทอร์เฟซสำหรับการแลกเปลี่ยนข้อมูลระหว่างเธรดหลัก และกระทู้ใหม่ : postMessage, onmessage
แล้วจะใช้งานอย่างไร มาดูตัวอย่างกัน:
//worker.jsonmessage =function (evt){ var d = evt.data;//รับข้อมูลที่ส่งผ่าน evt.data postMessage(d);//ส่งข้อมูลที่ได้รับไปยังเธรดหลัก}หน้า HTML: test.html
<!DOCTYPE HTML><html><head> <meta http-equiv=Content-Type content=text/html; charset=utf-8/> <script type=text/javascript>//เว็บเพจ เธรดหลัก var worker = new Worker(worker.js); //สร้างวัตถุ Worker และส่ง URL ของสคริปต์ที่จะดำเนินการในเธรดใหม่ worker.postMessage(hello world); //ส่งข้อมูลไปยัง worker worker.onmessage =function(evt){ //รับฟังก์ชันข้อมูล console.log(evt.data) จากผู้ปฏิบัติงาน; //ส่งออกข้อมูลที่ส่งจากผู้ปฏิบัติงาน} </script> </head> <body></body>< /html>หลังจากเปิด test.html ด้วยเบราว์เซอร์ Chrome คอนโซลจะส่งเอาต์พุตสวัสดีชาวโลก ซึ่งบ่งชี้ว่าโปรแกรมดำเนินการได้สำเร็จ
จากตัวอย่างนี้ เราจะเห็นว่าการใช้งาน Web Worker ส่วนใหญ่แบ่งออกเป็นส่วนต่างๆ ดังต่อไปนี้:
หัวข้อหลักของเว็บ:
1. โหลดไฟล์ JS ผ่าน worker = new Worker( url ) เพื่อสร้างผู้ปฏิบัติงานและส่งคืนอินสแตนซ์ของผู้ปฏิบัติงาน
2. ส่งข้อมูลไปยังผู้ปฏิบัติงานผ่านเมธอด worker.postMessage(data)
3. ผูกเมธอด worker.onmessage เพื่อรับข้อมูลที่ส่งโดยผู้ปฏิบัติงาน
4. คุณสามารถใช้ worker.terminate() เพื่อยุติการดำเนินการของผู้ปฏิบัติงาน
เธรดผู้ปฏิบัติงานใหม่:
1. ส่งข้อมูลไปยังเธรดหลักผ่านวิธี postMessage(data)
2. ผูกเมธอด onmessage เพื่อรับข้อมูลที่ส่งโดยเธรดหลัก
2: ผู้ปฏิบัติงานสามารถทำอะไรได้บ้าง?ตอนนี้เรารู้วิธีใช้ Web Worker แล้ว มันมีประโยชน์อะไร และมันสามารถช่วยเราแก้ปัญหาอะไรได้บ้าง ลองดูตัวอย่างลำดับฟีโบนักชีกัน
ดังที่เราทราบกันดีว่าในทางคณิตศาสตร์ ลำดับฟีโบนัชชีถูกกำหนดแบบวนซ้ำ: F0=0, F1=1, Fn=F(n-1)+F(n-2) (n>=2, n∈N*) การใช้งานจาวาสคริปต์ทั่วไปคือ:
var fibonacci =function(n) { return n <2? n : arguments.callee(n -1) + arguments.callee(n -2);};//fibonacci(36)เวลาดำเนินการของการใช้วิธีการนี้ในการคำนวณลำดับฟีโบนัชชีของ 39 ใน Chrome คือ 19097 มิลลิวินาที แต่เมื่อต้องคำนวณ 40 เบราว์เซอร์จะแจ้งโดยตรงว่าสคริปต์ไม่ว่าง
เนื่องจาก JavaScript ดำเนินการในเธรดเดียว เบราว์เซอร์จึงไม่สามารถเรียกใช้สคริปต์ JavaScript อื่น ๆ ได้ในระหว่างกระบวนการคำนวณลำดับ และเธรดการแสดงผล UI จะถูกระงับเช่นกัน ทำให้เบราว์เซอร์เข้าสู่สถานะซอมบี้ การใช้พนักงานเว็บเพื่อนำกระบวนการคำนวณของลำดับไปไว้ในเธรดใหม่จะช่วยหลีกเลี่ยงสถานการณ์นี้ได้ ดูตัวอย่างเฉพาะ:
//fibonacci.jsvar fibonacci =function(n) { return n <2? n : arguments.callee(n -1) + arguments.callee(n -2);};onmessage =function(event) { var n = parseInt (event.data, 10); postMessage(ฟีโบนัชชี(n));};หน้า HTML: fibonacci.html
<!DOCTYPE HTML><html><head><meta http-equiv=Content-Type content=text/html; charset=utf-8/><title>fibonacci ของผู้ปฏิบัติงานเว็บ</title><script type=text/javascript > onload =function(){ var worker = new Worker('fibonacci.js'); worker.addEventListener('message', function(event) { var timer2 = (new วันที่()).valueOf(); console.log( 'ผลลัพธ์:'+event.data, 'เวลา:'+ timer2, 'เวลาที่ถ่าย:'+ ( timer2 - จับเวลา ) }, var timer = ( วันที่ใหม่()).valueOf(); console.log('เริ่มการคำนวณ: 40', 'เวลา:' + ตัวจับเวลา ); setTimeout(function(){ console.log('ฟังก์ชันจับเวลาถูกดำเนินการเมื่อคำนวณลำดับ', 'เวลา:'+ (วันที่ใหม่()).valueOf() },1000); ฉันดำเนินการ ', 'time:'+ (new Date()).valueOf() ); } </script></head><body></body></html> เมื่อคำนวณลำดับเปิด fibonacci.html ใน Chrome และคอนโซลจะได้รับผลลัพธ์ต่อไปนี้:
เริ่มนับ: 40 เวลา: 1316508212705
เมื่อฉันคำนวณลำดับ ฉันดำเนินการเวลา: 1316508212734
ฟังก์ชันจับเวลาดำเนินการเมื่อคำนวณลำดับ: 1316508213735
ผลลัพธ์: 102334155 เวลา: 1316508262820 เวลาที่ผ่านไป: 50115
ตัวอย่างนี้แสดงให้เห็นว่าการคำนวณลำดับฟีโบนัชชีที่ดำเนินการในผู้ปฏิบัติงานไม่ส่งผลต่อการดำเนินการโค้ดของเธรดหลัก โดยจะมีการคำนวณอย่างสมบูรณ์ในเธรดอิสระของตัวเอง และผลลัพธ์จะถูกส่งกลับไปยังเธรดหลักหลังจากการคำนวณแล้วเท่านั้น สมบูรณ์.
ด้วยการใช้ Web Worker เราสามารถดำเนินการบางอย่างที่ซับซ้อนและมีขนาดใหญ่ในส่วนหน้าได้โดยไม่กระทบต่อการแสดงหน้า และข้อความแจ้งว่าสคริปต์ไม่ว่างจะไม่ปรากฏขึ้นมา
ตัวอย่างต่อไปนี้ใช้ Web Worker ในการคำนวณพิกเซลในฉาก เมื่อเปิดฉาก ฉากนั้นจะถูกวาดทีละพิกเซล
สาม: ความพยายามอื่นๆ โดยคนงานเรารู้อยู่แล้วว่า Worker สร้างผู้ปฏิบัติงานโดยรับ URL ดังนั้นเราจึงสามารถใช้ผู้ปฏิบัติงานเว็บเพื่อสร้างคำขอบางอย่างที่คล้ายกับ jsonp ได้หรือไม่ ดังที่เราทุกคนทราบ jsonp โหลดข้อมูล json โดยการแทรกแท็กสคริปต์ และองค์ประกอบสคริปต์กำลังโหลดและดำเนินการ กระบวนการทั้งหมดกำลังปิดกั้น คงจะดีมากถ้าคนทำงานเว็บสามารถใช้โหลดแบบอะซิงโครนัสได้
ตัวอย่างต่อไปนี้จะโหลดข้อมูล JSON ขนาด 169.42KB ผ่านวิธีการที่แตกต่างกัน 3 วิธี ได้แก่ web worker, jsonp และ ajax
// /aj/webWorker/core.jsfunction $E(id) { return document.getElementById(id);}onload =function() { //โหลดผ่าน web worker $E('workerLoad').onclick =function() { var url ='http://js.wcdn.cn/aj/mblog/face2'; var d = (วันที่ใหม่()).valueOf(); var worker =new ผู้ปฏิบัติงาน(url); worker.onmessage =function(obj) { console.log('web worker: '+ ((new Date()).valueOf() - d)); //โหลดผ่าน jsonp$ E('jsonpLoad').onclick =function() { var url ='http://js.wcdn.cn/aj/mblog/face1'; var d = (new วันที่()).valueOf(); STK.core.io.scriptLoader({ method:'post', url : url, onComplete : function() { console.log('jsonp: '+ ((วันที่ใหม่()) .valueOf() - d)); //โหลด $E('ajaxLoad') ผ่าน ajax.onclick =function() { var url ='http://js.wcdn.cn/aj/mblog/face'; var d = (วันที่ใหม่()).valueOf(); STK.core.io.ajax({ url : url, onComplete : function( json) { console.log('ajax: '+ ((วันที่ใหม่()).valueOf() - d) }); };};หน้า HTML:/aj/webWorker/worker.html
<!DOCTYPE HTML><html><head><meta http-equiv=Content-Type content=text/html; charset=utf-8/><title>ตัวอย่างผู้ปฏิบัติงาน: โหลดข้อมูล</title><script src=http //js.t.sinajs.cn/STK/js/gaea.1.14.js type=text/javascript></script><script type=text/javascript src=http://js.wcdn.cn/aj/webWorker/core.js></script></head><body> <input type=button id=workerLoad value=web worker load></input> < ประเภทอินพุต=ปุ่ม id=ค่า jsonpLoad=jsonp load></input> <ประเภทอินพุต=ปุ่ม id=ajaxLoad ค่า=โหลด jsonp></input></body></html>
ตั้งค่าโฮสต์
127.0.0.1 js.wcdn.cn
เข้าถึงเพจผ่าน http://js.wcdn.cn/aj/webWorker/worker.html จากนั้นโหลดข้อมูลด้วยสามวิธีเพื่อรับเอาต์พุตคอนโซล:
พนักงานเว็บ: 174jsonp: 25ajax: 38
หลังจากลองหลายครั้ง ฉันพบว่าความแตกต่างของเวลาระหว่างการโหลดข้อมูลผ่าน jsonp และ ajax นั้นไม่แตกต่างกันมากนัก และเวลาในการโหลดของ web worker ก็อยู่ในระดับสูงเสมอ ดังนั้นการใช้ web worker เพื่อโหลดข้อมูลยังคงค่อนข้างช้า ในกรณีที่มีข้อมูลจำนวนมาก ไม่มีข้อได้เปรียบ อาจต้องใช้เวลาสำหรับ Worker ในการเริ่มต้นเธรดใหม่ ไม่มีข้อได้เปรียบอื่นใดนอกจากการไม่ปิดกั้นระหว่างการโหลด
ผู้ปฏิบัติงานเว็บสามารถรองรับการโหลด js ข้ามโดเมนได้หรือไม่ คราวนี้เราเข้าถึงหน้าผ่าน http://127.0.0.1/aj/webWorker/worker.html เมื่อคลิกปุ่มโหลดผู้ปฏิบัติงานเว็บ จะไม่มีอะไรสะท้อนให้เห็นใน Chrome ข้อความแสดงข้อผิดพลาดต่อไปนี้ปรากฏขึ้น จากนี้เราสามารถทราบได้ว่าผู้ปฏิบัติงานเว็บไม่รองรับการโหลด JS ข้ามโดเมน ซึ่งเป็นข่าวร้ายสำหรับเว็บไซต์ที่ใช้ไฟล์แบบคงที่ไปยังเซิร์ฟเวอร์แบบคงที่แยกต่างหาก
ดังนั้น Web Worker จึงสามารถใช้เพื่อโหลดข้อมูล JSON ในโดเมนเดียวกันเท่านั้น และ Ajax ก็สามารถทำได้อยู่แล้ว และมีประสิทธิภาพและอเนกประสงค์มากกว่า ปล่อยให้คนงานทำสิ่งที่ดี
สี่: สรุปคนทำงานเว็บดูดีแต่กลับชั่วร้าย
สิ่งที่เราสามารถทำได้:
1. คุณสามารถโหลด JS เพื่อทำการคำนวณที่ซับซ้อนจำนวนมากโดยไม่ต้องหยุดกระบวนการหลัก และสื่อสารผ่าน postMessage, onmessage
2. คุณสามารถโหลดไฟล์สคริปต์เพิ่มเติมในผู้ปฏิบัติงานผ่านทาง importScripts(url)
3. คุณสามารถใช้ setTimeout(), clearTimeout(), setInterval() และ clearInterval()
4. คุณสามารถใช้ XMLHttpRequest เพื่อส่งคำขอได้
5. สามารถเข้าถึงคุณสมบัติบางอย่างของเนวิเกเตอร์ได้
มีข้อจำกัดอะไรบ้าง:
1. ไม่สามารถโหลด JS ข้ามโดเมนได้
2. รหัสภายในผู้ปฏิบัติงานไม่สามารถเข้าถึง DOM
3. เบราว์เซอร์ต่างๆ มีการใช้งาน Worker ที่แตกต่างกัน ตัวอย่างเช่น FF อนุญาตให้สร้างผู้ปฏิบัติงานใหม่ในผู้ปฏิบัติงาน แต่ Chrome ไม่อนุญาต
4. ไม่ใช่ทุกเบราว์เซอร์ที่รองรับคุณสมบัติใหม่นี้
ข้างต้นคือเนื้อหาทั้งหมดของบทความนี้ ฉันหวังว่ามันจะเป็นประโยชน์ต่อการศึกษาของทุกคน ฉันหวังว่าทุกคนจะสนับสนุน VeVb Wulin Network