ห้ามทำซ้ำโดยไม่ได้รับอนุญาต
1. การประมวลผลการคำนวณราคาแพง
บางทีลักษณะที่ซับซ้อนที่สุดในการพัฒนาแอปพลิเคชัน Javascript ที่ซับซ้อนก็คือลักษณะของอินเทอร์เฟซผู้ใช้แบบเธรดเดียว สถานการณ์ที่ดีที่สุดเมื่อ Javascript จัดการการโต้ตอบของผู้ใช้คือการตอบสนองช้า และสถานการณ์ที่เลวร้ายที่สุดคือการไม่ตอบสนองที่ทำให้เบราว์เซอร์หยุดทำงาน (เมื่อเรียกใช้ Javascript การดำเนินการอัปเดตทั้งหมดในเพจจะถูกระงับ) ด้วยเหตุนี้ จึงจำเป็นต้องลดการดำเนินการที่ซับซ้อนทั้งหมด (การคำนวณใดๆ ที่นานกว่า 100 มิลลิวินาที) ให้อยู่ในระดับที่สามารถจัดการได้ นอกจากนี้ หากสคริปต์ไม่หยุดหลังจากทำงานเป็นเวลาอย่างน้อย 5 วินาที เบราว์เซอร์บางตัว (เช่น Firefox และ Opera) จะสร้างกล่องพร้อมท์เพื่อเตือนผู้ใช้ว่าสคริปต์ไม่ตอบสนอง
นี่เป็นสิ่งที่ไม่พึงประสงค์อย่างเห็นได้ชัด และการสร้างอินเทอร์เฟซที่ไม่ตอบสนองนั้นไม่ดี อย่างไรก็ตาม กรณีนี้เกือบจะแน่นอนเมื่อคุณจำเป็นต้องประมวลผลข้อมูลจำนวนมาก (เช่น การประมวลผลองค์ประกอบ DOM หลายพันรายการ)
ในเวลานี้ตัวจับเวลามีประโยชน์อย่างยิ่ง เนื่องจากตัวจับเวลาสามารถหยุดการเรียกใช้โค้ด Javascript ได้อย่างมีประสิทธิภาพ จึงทำให้เบราว์เซอร์หยุดการทำงานของโค้ดที่กำลังรันได้ (ตราบใดที่แต่ละโค้ดไม่เพียงพอที่จะทำให้เบราว์เซอร์หยุดทำงาน) ด้วยเหตุนี้ เราจึงสามารถรวมการคำนวณแบบวนซ้ำแบบปกติแบบเข้มข้นเข้ากับการคำนวณแบบไม่บล็อกได้ ลองดูตัวอย่างต่อไปนี้ที่จำเป็นต้องมีการคำนวณประเภทนี้
ภารกิจที่ใช้เวลานาน:
<table><tbody></tbody></table>
// ปกติ, เข้มข้น, การดำเนินการ
ตาราง var = document.getElementsByTagName("tbody");
สำหรับ ( var i = 0; i < 2000; i++ ) {
var tr = document.createElement("tr");
สำหรับ ( var t = 0; t < 6; t++ ){
var td = document.createElement("td");
td.appendChild(document.createTextNode("" + t));
tr.ผนวกเด็ก(td);
-
ตารางผนวกเด็ก(tr);
-
-
ในตัวอย่างนี้ เราสร้างโหนด DOM ทั้งหมด 26,000 โหนดและเติมตัวเลขลงในตาราง ซึ่งมีราคาแพงเกินไปและมีแนวโน้มที่จะหยุดการทำงานของเบราว์เซอร์และป้องกันการโต้ตอบของผู้ใช้ตามปกติ เราสามารถแนะนำตัวจับเวลาในเรื่องนี้และรับผลลัพธ์ที่แตกต่างออกไปหรืออาจจะดีกว่าก็ได้
ใช้ตัวจับเวลาเพื่อแบ่งงานที่ต้องใช้เวลานาน:
<table><tbody></tbody></table>
ตาราง var = document.getElementsByTagName("tbody");
var i = 0, สูงสุด = 1999;
setTimeout(ฟังก์ชัน(){
สำหรับ ( ขั้นตอน var = i + 500; i < ขั้นตอน; i++ ) {
var tr = document.createElement("tr");
สำหรับ ( var t = 0; t < 6; t++ ){
var td = document.createElement("td");
td.appendChild(document.createTextNode("" + t));
tr.ผนวกเด็ก(td);
-
-
ตารางผนวกเด็ก(tr);
-
ถ้า ( ฉัน < สูงสุด )
setTimeout(อาร์กิวเมนต์.callee, 0 );
}, 0);
ในตัวอย่างที่แก้ไขแล้ว เราแบ่งการคำนวณแบบเข้มข้นออกเป็นสี่ส่วน โดยแต่ละส่วนจะสร้างโหนดได้ 6,500 โหนด การคำนวณเหล่านี้ไม่น่าจะขัดจังหวะการทำงานปกติของเบราว์เซอร์ สถานการณ์กรณีที่เลวร้ายที่สุดคือตัวเลขเหล่านี้สามารถปรับได้ตลอดเวลา (เช่น กำหนดให้แตกต่างกันระหว่าง 250-500 เพื่อให้แต่ละเซลล์ของเราสร้างโหนด DOM 3500 รายการ) แต่สิ่งที่น่าประทับใจที่สุดคือวิธีที่เราเปลี่ยนโค้ดของเราเพื่อปรับให้เข้ากับระบบอะซิงโครนัสใหม่ เราจำเป็นต้องทำงานเพิ่มเติมเพื่อให้แน่ใจว่าตัวเลขสำหรับองค์ประกอบนั้นถูกสร้างขึ้นอย่างถูกต้อง (การวนซ้ำจะไม่สิ้นสุดตลอดไป) รหัสคล้ายกับรหัสดั้งเดิมของเรามาก โปรดทราบว่าเราใช้การปิดเพื่อรักษาสถานะการวนซ้ำระหว่างส่วนของโค้ด หากไม่มีการปิด โค้ดนี้จะซับซ้อนมากขึ้นอย่างไม่ต้องสงสัย
มีการเปลี่ยนแปลงที่ชัดเจนเมื่อใช้เทคโนโลยีนี้เมื่อเทียบกับของเดิม เบราว์เซอร์ค้างนานจะถูกแทนที่ด้วยการอัปเดตหน้าภาพ 4 ครั้ง แม้ว่าเบราว์เซอร์จะพยายามรันโค้ดเหล่านี้โดยเร็วที่สุด แต่ก็ยังแสดงการเปลี่ยนแปลง DOM (เช่น การอัปเดตจำนวนมาก) หลังจากแต่ละขั้นตอนของตัวจับเวลา ในกรณีส่วนใหญ่ ผู้ใช้จะไม่ทราบถึงการอัปเดตประเภทนี้ แต่สิ่งสำคัญคือต้องจำไว้ว่าการอัปเดตเหล่านี้เกิดขึ้น
มีสถานการณ์หนึ่งที่เทคโนโลยีนี้จะทำงานให้ฉันโดยเฉพาะ นั่นคือแอปพลิเคชันที่ฉันสร้างขึ้นเพื่อคำนวณตารางเวลาของนักศึกษา ในตอนแรก แอปพลิเคชันเป็นแบบ CGI ทั่วไป (ไคลเอนต์พูดคุยกับเซิร์ฟเวอร์ เซิร์ฟเวอร์คำนวณกำหนดการและส่งคืน) แต่ฉันเปลี่ยนมันและนำการคำนวณกำหนดการทั้งหมดไปที่ไคลเอนต์ นี่คือมุมมองของการคำนวณกำหนดการ:
การคำนวณเหล่านี้มีราคาค่อนข้างแพง (ต้องเปลี่ยนวิธีเรียงสับเปลี่ยนนับพันครั้งเพื่อหาคำตอบที่ถูกต้อง) ปัญหานี้แก้ไขได้โดยการแบ่งการคำนวณกำหนดการออกเป็นหน่วยจริง (อัปเดตอินเทอร์เฟซผู้ใช้ด้วยส่วนที่เสร็จสมบูรณ์) ในท้ายที่สุด ผู้ใช้ก็มอบอินเทอร์เฟซผู้ใช้ที่รวดเร็ว ตอบสนอง และใช้งานได้
มักเป็นเรื่องที่น่าแปลกใจว่าเทคโนโลยีมีประโยชน์ได้อย่างไร คุณจะพบว่ามันมักใช้ในโปรแกรมที่ใช้เวลานาน เช่น กล่องทดสอบ (เราจะพูดถึงเรื่องนี้ในตอนท้ายของบทนี้) ที่สำคัญกว่านั้น เทคโนโลยีนี้แสดงให้เราเห็นว่าการแก้ไขข้อจำกัดของสภาพแวดล้อมเบราว์เซอร์นั้นง่ายดายเพียงใด ในขณะเดียวกันก็มอบประสบการณ์อันยาวนานให้กับผู้ใช้ด้วย