Web Worker โดยเฉพาะ (Web Worker โดยเฉพาะ) เป็นวิธีง่ายๆในการอนุญาตให้เนื้อหาเว็บเรียกใช้สคริปต์ในพื้นหลัง เมื่อผู้ปฏิบัติงานถูกสร้างขึ้นมันสามารถส่งข้อความไปยังฟังก์ชั่นการตรวจสอบเหตุการณ์ที่ระบุโดยผู้สร้างเพื่อให้งานทั้งหมดที่สร้างโดยผู้ปฏิบัติงานจะได้รับข้อความเหล่านี้ เธรดคนงานสามารถทำงานได้โดยไม่ต้องมีสัญญาณรบกวน UI นอกจากนี้ยังสามารถใช้ XMLHTTTPREQUEST (แม้ว่าค่าแอตทริบิวต์ทั้งสองของ Responsexml และช่องจะเป็นโมฆะเสมอ) เพื่อดำเนินการ I/O บทความนี้แสดงตัวอย่างและรายละเอียดเพื่อจัดทำเอกสารก่อนหน้า ฟังก์ชั่นที่ให้ไว้กับคนงานแสดงรายการฟังก์ชั่นที่สนับสนุนโดยคนงาน
อินเทอร์เฟซของคนงานจะสร้างเธรดระบบปฏิบัติการจริง อย่างไรก็ตามสำหรับผู้ปฏิบัติงานเว็บจุดสื่อสารที่มีเธรดอื่น ๆ จะถูกควบคุมอย่างระมัดระวังซึ่งหมายความว่ามันยากสำหรับคุณที่จะก่อให้เกิดภาวะแทรกซ้อน คุณไม่มีวิธีในการเข้าถึงส่วนประกอบความปลอดภัยที่ไม่ใช่เธรดหรือ DOM ดังนั้นหากคุณไม่ได้ใช้ความพยายามคุณไม่สามารถทำผิดพลาดได้ สร้างคนงาน
มันง่ายมากที่จะสร้างคนงานใหม่ สิ่งที่คุณต้องทำคือเรียกตัวสร้าง Worker () และระบุ URI ที่ต้องการเรียกใช้สคริปต์ที่ทำงานอยู่ในเธรดคนงาน ฟังก์ชั่นการประมวลผลเหตุการณ์เฉพาะ
var myworker = คนงานใหม่ (my_task.js);
หรือคุณสามารถใช้ addeventListener ():
var myworker = คนงานใหม่ (my_task.js); คนงาน
บรรทัดแรกในตัวอย่างสร้างเธรดคนงานใหม่ พระราชบัญญัติที่สามตั้งค่าฟังก์ชั่นการตรวจสอบของเหตุการณ์ข้อความ เมื่อคนงานเรียกฟังก์ชั่น postmessage () ของตัวเองฟังก์ชั่นการประมวลผลเหตุการณ์นี้เรียกว่า ในที่สุดเธรดคนงานก็เปิดตัวในสายที่เจ็ด หมายเหตุ: พารามิเตอร์ URI ที่ส่งผ่านตัวสร้างคนงานจะต้องปฏิบัติตามกลยุทธ์ที่คล้ายคลึงกัน ในปัจจุบันผู้ผลิตเบราว์เซอร์ที่แตกต่างกันยังคงแตกต่างกันซึ่ง URIS ควรทำตามกลยุทธ์ที่คล้ายคลึงกัน BLOB URI
ผ่านข้อมูลข้อมูลที่ส่งระหว่างหน้าแรกและคนงานถูกคัดลอกไม่แชร์ วัตถุที่ส่งผ่านไปยังคนงานจะต้องได้รับการจัดลำดับจากนั้นปลายถัดไปจะต้องมีการจัดลำดับ หน้าไม่แชร์ตัวอย่างเดียวกันกับผู้ปฏิบัติงาน เบราว์เซอร์ส่วนใหญ่ใช้สำเนาที่มีโครงสร้างเพื่อให้ได้คุณสมบัตินี้
ก่อนที่จะลงไปเพื่อจุดประสงค์ในการสอนให้เราสร้างฟังก์ชั่นที่เรียกว่า EmulatingMessage ()
ฟังก์ชั่น EmulatingMessage (VVAL) {return eval; บูลีน // ทดสอบ #3V #3V AR ตัวอย่าง 3 = สตริงใหม่ (Hello World); , อายุ: 43}; VAR ตัวอย่าง 5 สัตว์ (CAT, 3);ค่าที่ไม่ได้แชร์เรียกว่าข้อความ พูดคุยเกี่ยวกับคนงานกันเถอะคุณสามารถใช้ postmessage () เพื่อส่งข้อความไปยังเธรดหลักหรือส่งกลับจากเธรดหลัก แอตทริบิวต์ข้อมูลของเหตุการณ์ข้อความมีข้อมูลจากคนงาน
example.html: (หน้าแรก):var myworker = คนงานใหม่ (my_task.js); ;
หมายเหตุ: โดยทั่วไปการพูดหัวข้อพื้นหลัง -รวมถึงคนงาน -ไม่สามารถใช้งาน DOM ได้ หากเธรดพื้นหลังจำเป็นต้องแก้ไข DOM นั้นควรส่งข้อความไปยังผู้ก่อตั้งเพื่อให้ผู้สร้างดำเนินการเหล่านี้ให้เสร็จสมบูรณ์
อย่างที่คุณเห็นข้อความที่ส่งระหว่างคนงานและหน้าแรกมักจะเป็น "ข้อความ JSON" แม้ว่าจะเป็นค่าดั้งเดิม ดังนั้นคุณสามารถส่งข้อมูล JSON และ/หรือประเภทข้อมูลใด ๆ ที่สามารถทำให้เป็นอนุกรม:
postmessage ({cmd: init, timestamp: date.now ()});ตัวอย่างที่จะส่งผ่านข้อมูล
ตัวอย่าง#1: สร้าง "assynchronous eval ()" ทั่วไป
ตัวอย่างต่อไปนี้แนะนำวิธีการใช้ eval () ในคนงานเพื่อเรียกใช้รหัส JavaScript ทุกประเภทในแบบอะซิงโครนัสทุกประเภทตามลำดับ ::
// ไวยากรณ์: asynceval (รหัส [, listner]) var asynceval = (function () {var alistener = [], oparser = คนงานใหม่ (ข้อมูล: ข้อความ/javascript; charset = us-asciii, onmessage%20%3d%20function %20%28oevent%29%20%7B%0A%09POSTMESSAGE%28%7B%09%09%22ID%22%22%20OEVENT 20EVAL%28OEVENT.DATA.CODE%29%0A%09%7D%29%3B%0A%7D); data.id] (eevent.data.evaluated);} ลบ alisteners [eevent.data.id];}; : alisteners.length -1, รหัส: scode});};});ตัวอย่างการใช้:
// ข้อความแจ้งเตือนแบบอะซิงโครนัส ... asynceval (3 + 2, ฟังก์ชั่น (smessage) {การแจ้งเตือน (3 + 2 = + smessage); // การพิมพ์แบบอะซิงโครนัส ... Asynceval (// Hello World !!!/,,, (shtml) {document.body.appendchild (document.createtextnode (shtml);}); .Open (/get/, /http://www.mozilla.org//, false);/n/toreq.send (null);/n/treturn oreq.responsetext;/n}););); ;ตัวอย่าง#2: ถ่ายโอนวิธีการขั้นสูงของ JSON และสร้างระบบแลกเปลี่ยน
หากคุณต้องการส่งข้อมูลที่ซับซ้อนมากและคุณต้องโทรหาหลายวิธีในหน้าแรกและคนงานในเวลาเดียวกันคุณสามารถพิจารณาสร้างระบบที่คล้ายกับต่อไปนี้
example.html (หน้าหลัก): <! อาร์กิวเมนต์ที่จะผ่าน 1, อาร์กิวเมนต์ที่จะผ่าน 2, ฯลฯ ฯลฯ ): เรียกฟังก์ชั่นการสืบค้นของคนงาน * postmessage (ข้อมูลสตริงหรือ JSON): ดูคนงาน Protodype ฟังก์ชั่น): เพิ่มผู้ฟัง * RemoveListener (ชื่อ): ลบคุณสมบัติอินสแตนซ์ของผู้ฟัง: * defaultListListener: ผู้ฟังเริ่มต้น executem เฉพาะเมื่อคนงานเรียกฟังก์ชั่น postmessage () โดยตรง */ ฟังก์ชั่น queryableworker (surl, fdeflistener, fonerror) OINSTANCE = สิ่งนี้ OWORCER = คนงานใหม่ (SURL), OliStener = {}; .data.hasownproperty (rnb93qh) {olisteners [eevent.data.vo42t30] .apply (oievent.data.rnb99 3QH); {owster.onerror = fonerror;} this.sendQuery = function (/ * ชื่อฟังก์ชั่นที่สามารถสอบถามได้, อาร์กิวเมนต์ที่จะผ่าน 1, อาร์กิวเมนต์ที่จะผ่าน 2, 2, 2, ฯลฯ ฯลฯ */) {ถ้า (อาร์กิวเมนต์ความยาว <1) { โยน typerror ใหม่ (queryableworker.sendQuery -อาร์กิวเมนต์ไม่เพียงพอ); = function (VMSG) {// ฉันแค่คิดว่าไม่จำเป็นต้องใช้การโทร () วิธีการที่จะออกจาก (VMSG); Prototy Worker.prototype.postMessage.call (Oworker, VMSG); ] = flistener;}; this.RemoVelistener = function (sname) {ลบ olistener [sname];}; ] * /); ); id = firstLink href = javascript: omytask.sendQuery ('getDifferente', 5, 3);> ความแตกต่างระหว่าง 5 และ 3 คืออะไร? omytask.sendQuery ('waitsomething'); ) {// ทำบางสิ่งบางอย่าง} funct} funct ion myprivatefunc2 () {// ทำบางสิ่งบางอย่าง} // ฯลฯ ฯลฯ // ฟังก์ชั่นสาธารณะที่กำหนดเองของคุณ รับการเดิมพันที่แตกต่างกัน ween สอง nightrs: getDifference: ฟังก์ชั่น (nminund, nsubtrahend) {ตอบกลับ (พิมพ์บางอย่าง, nminuend -nsubtrahend);}, // ตัวอย่าง #2: รอสามวินาทีรอ: ฟังก์ชั่น () tsomething, 3, sex);}, 3000);}}; (/ * ชื่อผู้ฟัง, อาร์กิวเมนต์ที่จะผ่าน 1, อาร์กิวเมนต์ที่จะผ่าน 2, ฯลฯ ฯลฯ */) {ถ้า (อาร์กิวเมนต์ความยาว <1) {โยน typerror ใหม่ (ตอบ -ไม่ใช่อาร์กิวเมนต์ Enugh); : อาร์กิวเมนต์ [0], rnb93qh: array.prototype.slice .call (อาร์กิวเมนต์, 1)});} onMessage = ฟังก์ชั่น (oEvent) {ถ้า (eevent.data อินสแตนซ์ของวัตถุ && sownproperty) && daeenproprty (bk4e1h0) {queryableFunction [eevent.data .bk4e1h0] .apply (self, oevent.data.ktp3fm1);} else {defaultQuery (eevent.data);}};นี่เป็นวิธีที่เหมาะสมมากในการสลับข่าวระหว่างโฮมเพจ-คนงาน-หรือตรงกันข้ามตรงข้ามตรงกันข้าม
ถ่ายโอนข้อมูลโดยการถ่ายโอนความเป็นเจ้าของ (วัตถุที่ถ่ายโอนได้)
Google Chrome 17 และ Firefox 18 รวมถึงวิธีอื่นที่มีประสิทธิภาพสูงกว่าเพื่อส่งผ่านประเภทของวัตถุ (วัตถุที่ถ่ายโอนได้) ไปยังคนงาน/กลับจากคนงาน วัตถุการถ่ายโอนจะถูกถ่ายโอนจากบริบทหนึ่งไปยังบริบทอื่นโดยไม่มีการดำเนินการคัดลอกใด ๆ ซึ่งหมายความว่ามันจะได้รับการปรับปรุงประสิทธิภาพที่ยอดเยี่ยมเมื่อผ่านข้อมูลขนาดใหญ่ หากคุณมาจากโลก C/C ++ ลองจินตนาการว่ามันเป็นระบบส่งกำลังตามการอ้างอิง อย่างไรก็ตามแตกต่างจากการถ่ายทอดตามการอ้างอิงเมื่อวัตถุถูกถ่ายโอนเวอร์ชันที่บริบทดั้งเดิมจะไม่มีอยู่อีกต่อไป ความเป็นเจ้าของของวัตถุจะถูกถ่ายโอนไปยังบริบทใหม่ ตัวอย่างเช่นเมื่อคุณถ่ายโอนวัตถุ ArrayBuffer จากแอปพลิเคชันหลักไปยังผู้ปฏิบัติงาน ArrayBuffer ดั้งเดิมจะถูกล้างและไม่สามารถใช้งานได้ เนื้อหาที่มี (เสร็จสมบูรณ์) จะถูกส่งผ่านไปยังบริบทของคนงาน
// สร้างไฟล์ 32MB และเติมเต็ม uint8array = ใหม่ uint8aray (1024*1024*32); ;สร้างงานย่อย
หากจำเป็นคนงานสามารถสร้างพนักงานได้มากขึ้น สิ่งนี้เรียกว่างานย่อยที่ต้องโฮสต์ในแหล่งเดียวกับหน้าหลัก ในทำนองเดียวกันคนงานย่อยวิเคราะห์ที่อยู่ของ URI มากกว่าหน้าของเขาเองแทนที่จะเป็นหน้าของตัวเอง สิ่งนี้ทำให้คนงานตรวจสอบการพึ่งพาอาศัยกันได้อย่างง่ายดาย Chrome ไม่รองรับงานย่อย
คนงานฝังขณะนี้ไม่มีวิธีการ "เป็นทางการ" ที่สามารถฝังรหัสคนงานลงในหน้าเว็บเช่นองค์ประกอบ <script> แต่ถ้าองค์ประกอบ <script> ไม่มีลักษณะ SRC และลักษณะประเภทของมันไม่ได้ระบุว่าเป็นประเภท MIME ที่กำลังทำงานอยู่มันจะถูกพิจารณาว่าเป็นองค์ประกอบบล็อกข้อมูลและสามารถใช้งานได้โดย JavaScript "Data Block" เป็นคุณสมบัติที่พบบ่อยมากใน HTML5 ซึ่งสามารถนำข้อมูลประเภทข้อความได้เกือบทุกประเภท ดังนั้นคุณสามารถฝังคนงานด้วยวิธีต่อไปนี้:
<! . การวิเคราะห์เครื่องยนต์เพราะประเภท MIME คือ Text/JS-Worker var myvar = Hello World!; </script> <script type = text/javascript> // สคริปต์จะถูกวิเคราะห์โดยเอ็นจิ้น JS เนื่องจาก MIME-type เป็นข้อความ/JavaScript ฟังก์ชั่น pagelog (smsg) {// ใช้แฟรกเมนต์: ด้วยวิธีนี้เบราว์เซอร์จะแสดงผล/rearring เท่านั้น var ofragm = document.createdocumentfragment (); -Workr> // สคริปต์นี้จะไม่ถูกแยกวิเคราะห์โดยเครื่องยนต์ JS เพราะประเภท MIME คือ Text/JS-Worker onMessage = ฟังก์ชั่น (oEvent) {postmessage (myVar);}; // รหัสคนงานที่เหลือเขียนไว้ที่นี่ </script> <script type = text/javascript> // สคริปต์จะถูกวิเคราะห์โดยเอ็นจิ้น JS เนื่องจาก MIME-type เป็นข้อความ/JavaScript // ในอดีต ... : // เราใช้ blob builder // ... แต่ตอนนี้เราใช้ blob ... : var blob = blob ใหม่ (array.prototype.map.call (documens.quelySelectorary (สคริปต์ [ประเภท = =/text // js- workr/], function (oscript) {return oscript.textcontent;}), {type: text/javascript}); . สคริปต์คนงาน document.worker = คนงานใหม่ (window.url.createObjecturl (blob)); () {document.worker.postMessage ();};ตอนนี้คนงานที่ฝังตัวถูกตั้งค่าไว้ในเอกสารที่กำหนดเองคุณสมบัติของคนงาน
หมดเวลาและช่วงเวลาคนงานสามารถใช้การหมดเวลาและช่วงเวลาเช่นเธรดหลัก สิ่งนี้จะมีประโยชน์มากตัวอย่างเช่นหากคุณต้องการให้เธรดคนงานเป็นระยะโดยไม่ต้องใช้รหัสการรันอย่างต่อเนื่อง
พนักงานเลิกจ้างหากคุณต้องการยกเลิกคนงานทันทีคุณสามารถโทรหาวิธีการยุติ () ของคนงาน ::
myworker.terminate ();
เธรดคนงานจะถูกฆ่าตายทันทีและจะไม่ปล่อยให้มีโอกาสใด ๆ ที่จะปล่อยให้การดำเนินงานของตัวเองเสร็จสมบูรณ์หรือทำความสะอาด
คนงานสามารถเรียกวิธีการ nsiworkerscope.close () ของคุณเองเพื่อปิดตัวเอง:
self.close ();ประมวลผลข้อผิดพลาด
เมื่อคนงานมีข้อผิดพลาดรันไทม์ฟังก์ชั่นการประมวลผลเหตุการณ์ onerror จะถูกเรียก จะได้รับเหตุการณ์ที่ใช้ข้อผิดพลาดชื่ออินเตอร์เฟสข้อผิดพลาด เหตุการณ์จะไม่เดือดร้อนและสามารถยกเลิกได้ เหตุการณ์ข้อผิดพลาดมีสามฟิลด์ต่อไปนี้ที่สนใจ:
ข้อความข้อความแสดงข้อผิดพลาดที่อ่านได้
ชื่อไฟล์ชื่อไฟล์สคริปต์ข้อผิดพลาด
ผ้าลินินหมายเลขบรรทัดของไฟล์สคริปต์เมื่อเกิดข้อผิดพลาด
เยี่ยมชมวัตถุ Navigatorคนงานสามารถเข้าถึงวัตถุ Navigator ในขอบเขต มันมีสตริงต่อไปนี้ที่สามารถจดจำเบราว์เซอร์ได้เช่นเดียวกับที่ทำในสคริปต์ทั่วไป:
เธรดคนงานสามารถเข้าถึงฟังก์ชั่นทั่วโลก, importScripts () ซึ่งช่วยให้คนงานสามารถแนะนำสคริปต์หรือไลบรารีในขอบเขตของตัวเอง คุณสามารถแนะนำ URI โดยไม่ต้องผ่านพารามิเตอร์หรือไปยัง URI ของสคริปต์หลายตัวอย่าง
importScripts (); */
เบราว์เซอร์โหลดและเรียกใช้สคริปต์ วัตถุส่วนกลางในแต่ละสคริปต์สามารถใช้งานได้โดยคนงาน หากสคริปต์ไม่สามารถโหลดได้ข้อยกเว้น Network_ERROR จะถูกโยนลงไปและรหัสถัดไปจะไม่ถูกเรียกใช้งาน รหัสที่ดำเนินการก่อนหน้านี้ (รวมถึงรหัสที่ดำเนินการโดยใช้ window.settimeout ()) ยังสามารถใช้งานได้ การประกาศฟังก์ชั่นหลังจากนำเข้า () ยังสามารถใช้งานได้เพราะพวกเขามักจะทำงานก่อนรหัสอื่น หมายเหตุ: ลำดับการดาวน์โหลดของสคริปต์ไม่ได้รับการแก้ไข แต่คำสั่งจะถูกส่งผ่านไปยัง importScripts () () เมื่อดำเนินการ สิ่งนี้เสร็จสิ้นพร้อมกัน
ตัวอย่างส่วนนี้มีตัวอย่างหลายประการเกี่ยวกับวิธีการใช้ DOM Worker
ดำเนินการในพื้นหลัง
ข้อดีอย่างหนึ่งของผู้ปฏิบัติงานคือสามารถดำเนินการการทำงานที่หนาแน่นของโปรเซสเซอร์โดยไม่ต้องปิดกั้นเธรด UI ในตัวอย่างต่อไปนี้คนงานจะใช้ในการคำนวณ fibona
รหัส JavaScript
รหัส JavaScript ต่อไปนี้จะถูกเก็บไว้ในไฟล์ "fibonacci.js" ซึ่งเชื่อมโยงกับไฟล์ HTML ในส่วนถัดไป
ผลลัพธ์ var = []; ฟังก์ชั่น errorreceiver (เหตุการณ์) {throw event.data;} onMessage = ฟังก์ชั่น (เหตุการณ์) {var n = parseint (event.data); } สำหรับ (var i = 1; i <= 2; i ++) {var worker = คนงานใหม่ (fibonacci.js);ผู้ปฏิบัติงานตั้งค่าแอตทริบิวต์ onMessage เป็นฟังก์ชัน (โปรดทราบว่าการใช้งานนี้ไม่เหมือนกับการกำหนดตัวแปรส่วนกลางที่มีชื่อเดียวกันหรือฟังก์ชั่นของชื่อเดียวกัน ข้อความที่ส่งโดยหน้าเว็บ) สิ่งนี้จะเปิดใช้งานการเรียกซ้ำและสร้างสำเนาใหม่ของคุณเพื่อประมวลผลแต่ละรอบของการคำนวณ
รหัส HTML
<! = คนงานใหม่ (fibonacci.js); = ฟังก์ชั่น (ข้อผิดพลาด) {dump (ข้อผิดพลาดของผู้ปฏิบัติงาน: + ข้อผิดพลาด message +/n);หน้าเว็บสร้างองค์ประกอบ DIV, ID เป็นผลลัพธ์โดยใช้เพื่อแสดงผลการคำนวณจากนั้นสร้างคนงาน หลังจากสร้างคนงานแล้วฟังก์ชั่นการประมวลผล onMessage จะถูกกำหนดค่าให้แสดงผลการคำนวณโดยการตั้งค่าเนื้อหาขององค์ประกอบ DIV จากนั้นฟังก์ชันการประมวลผล ONERROR จะถูกตั้งค่าเป็นข้อมูลข้อผิดพลาดการจัดเก็บข้อมูล สุดท้ายส่งข้อความถึงคนงานเพื่อเริ่มต้น