เพิ่มประสิทธิภาพงานที่ใช้เวลานาน

คุณเคยได้ยินว่า "อย่าบล็อกเธรดหลัก" และ "แบ่งงานที่มีระยะเวลานาน" แต่การทําเช่นนั้นหมายความว่าอย่างไร

คำแนะนำทั่วไปในการทำให้แอป JavaScript ทำงานได้อย่างรวดเร็วมักจะสรุปเป็นคำแนะนำต่อไปนี้

  • "อย่าบล็อกชุดข้อความหลัก"
  • "แบ่งงานใหญ่ออกเป็นงานย่อยๆ"

นี่เป็นคำแนะนำที่ดีมาก แต่ต้องทํางานอะไรบ้าง การใช้ JavaScript น้อยลงเป็นสิ่งที่ดี แต่การทำเช่นนี้จะทำให้อินเทอร์เฟซผู้ใช้ตอบสนองมากขึ้นโดยอัตโนมัติหรือไม่ อาจจะเป็นไปได้ หรือไม่ก็อาจจะไม่

หากต้องการทำความเข้าใจวิธีเพิ่มประสิทธิภาพงานใน JavaScript ก่อนอื่นคุณต้องทราบว่างานคืออะไรและเบราว์เซอร์จัดการกับงานเหล่านั้นอย่างไร

งานคืออะไร

งานคืองานที่เบราว์เซอร์ทำแยกกัน ซึ่งรวมถึงการแสดงผล การแยกวิเคราะห์ HTML และ CSS การรัน JavaScript และงานประเภทอื่นๆ ที่คุณอาจไม่สามารถควบคุมได้โดยตรง งานนี้ JavaScript ที่คุณเขียนอาจเป็นแหล่งที่มาของงานมากที่สุด

ภาพแสดงงานตามที่แสดงในเครื่องมือวัดประสิทธิภาพของเครื่องมือสำหรับนักพัฒนาเว็บของ Chrome งานจะอยู่ที่ด้านบนของกลุ่ม โดยมีเครื่องจัดการกิจกรรมการคลิก การเรียกใช้ฟังก์ชัน และรายการอื่นๆ อยู่ด้านล่าง งานนี้ยังแสดงภาพงานบางส่วนทางด้านขวามือด้วย
งานที่เริ่มต้นโดยเครื่องจัดการเหตุการณ์ click ซึ่งแสดงในเครื่องมือสร้างโปรไฟล์ประสิทธิภาพของ Chrome DevTools

งานที่เกี่ยวข้องกับ JavaScript จะส่งผลต่อประสิทธิภาพใน 2 วิธีดังนี้

  • เมื่อดาวน์โหลดไฟล์ JavaScript ระหว่างเริ่มต้นใช้งาน เบราว์เซอร์จะจัดคิวงานเพื่อแยกวิเคราะห์และคอมไพล์ JavaScript ดังกล่าวเพื่อให้เรียกใช้ภายหลังได้
  • ในช่วงเวลาอื่นๆ ตลอดอายุการใช้งานของหน้าเว็บ ระบบจะจัดคิวงานเมื่อ JavaScript ทํางาน เช่น กระตุ้นการโต้ตอบผ่านตัวแฮนเดิลเหตุการณ์ ภาพเคลื่อนไหวที่ขับเคลื่อนโดย JavaScript และกิจกรรมเบื้องหลัง เช่น การเก็บรวบรวมข้อมูลวิเคราะห์

การดำเนินการทั้งหมดนี้ (ยกเว้น Web Worker และ API ที่คล้ายกัน) จะเกิดขึ้นในเธรดหลัก

เทรดหลักคืออะไร

เธรดหลักคือที่ที่งานส่วนใหญ่ทำงานในเบราว์เซอร์ และที่ที่ JavaScript เกือบทั้งหมดที่คุณเขียนจะทำงาน

เทรดหลักจะประมวลผลงานได้ครั้งละ 1 งานเท่านั้น งานที่ใช้เวลานานกว่า 50 มิลลิวินาทีถือเป็นงานที่ใช้เวลานาน สำหรับงานที่ใช้เวลานานกว่า 50 มิลลิวินาที เวลาทั้งหมดของงานลบด้วย 50 มิลลิวินาทีเรียกว่าระยะเวลาการบล็อกของงาน

เบราว์เซอร์จะบล็อกไม่ให้เกิดการโต้ตอบขณะที่งานกำลังทำงานอยู่ไม่ว่างานจะยาวแค่ไหนก็ตาม แต่ผู้ใช้จะไม่สังเกตเห็นการทำงานนี้ตราบใดที่งานไม่ทำงานนานเกินไป แต่เมื่อผู้ใช้พยายามโต้ตอบกับหน้าเว็บเมื่อมีงานยาวๆ หลายงาน อินเทอร์เฟซผู้ใช้จะรู้สึกว่าไม่ตอบสนอง และอาจทำงานเสียหายได้หากเทรดหลักถูกบล็อกเป็นเวลานาน

งานที่มีระยะเวลานานในเครื่องมือวิเคราะห์ประสิทธิภาพของ DevTools ใน Chrome ส่วนการบล็อกของงาน (มากกว่า 50 มิลลิวินาที) จะแสดงด้วยลายเส้นทแยงมุมสีแดง
งานที่ใช้เวลานานตามที่แสดงในเครื่องมือสร้างโปรไฟล์ประสิทธิภาพของ Chrome งานที่มีความยาวจะแสดงด้วยรูปสามเหลี่ยมสีแดงที่มุมของงาน โดยส่วนที่บล็อกของงานจะมีลายเส้นสีแดงทแยงมุม

คุณสามารถแบ่งงานที่มีขนาดใหญ่ออกเป็นงานเล็กๆ หลายงานเพื่อป้องกันไม่ให้เทรดหลักถูกบล็อกเป็นเวลานาน

งานเดียวที่ใช้เวลานานกับงานเดียวกัน โดยแบ่งออกเป็นงานที่สั้นลง งานแบบยาวเป็นรูปสี่เหลี่ยมผืนผ้าขนาดใหญ่ 1 รูป ส่วนงานแบบแบ่งเป็นชิ้นๆ เป็นรูปสี่เหลี่ยมผืนผ้าขนาดเล็ก 5 รูปที่มีความกว้างรวมเท่ากับงานแบบยาว
การแสดงภาพงานยาวรายการเดียวเทียบกับงานเดียวกันที่แบ่งออกเป็นงานสั้นๆ 5 รายการ

การดำเนินการนี้สำคัญเนื่องจากเมื่อแบ่งงานออกเป็นหลายส่วนแล้ว เบราว์เซอร์จะตอบสนองต่องานที่มีความสำคัญสูงกว่าได้เร็วขึ้นมาก รวมถึงการโต้ตอบของผู้ใช้ด้วย หลังจากนั้น ระบบจะเรียกใช้งานที่เหลือจนเสร็จสมบูรณ์ เพื่อให้งานที่คุณจัดคิวไว้ตั้งแต่แรกเสร็จสมบูรณ์

ภาพแสดงว่าการแบ่งงานช่วยให้ผู้ใช้โต้ตอบได้ง่ายขึ้นได้อย่างไร ที่ด้านบน งานที่ใช้เวลานานจะบล็อกไม่ให้ตัวแฮนเดิลเหตุการณ์ทำงานจนกว่าจะเสร็จ ที่ด้านล่าง งานที่มีการแบ่งออกเป็นหลายส่วนจะอนุญาตให้ตัวแฮนเดิลเหตุการณ์ทำงานได้เร็วขึ้น
การแสดงภาพสิ่งที่จะเกิดขึ้นกับการโต้ตอบเมื่องานยาวเกินไป และเบราว์เซอร์ตอบสนองการโต้ตอบได้ไม่เร็วพอ เมื่อเทียบกับเมื่องานที่ใช้เวลานานถูกแบ่งออกเป็นงานย่อยๆ

ที่ด้านบนของรูปภาพก่อนหน้า ตัวแฮนเดิลเหตุการณ์ที่จัดคิวไว้โดยการโต้ตอบของผู้ใช้ต้องรองานระยะยาวรายการเดียวก่อนจึงจะเริ่มได้ ซึ่งทำให้การโต้ตอบล่าช้า ในกรณีนี้ ผู้ใช้อาจสังเกตเห็นความล่าช้า ที่ด้านล่าง ตัวแฮนเดิลเหตุการณ์จะเริ่มทํางานเร็วขึ้น และผู้ใช้อาจรู้สึกว่าการโต้ตอบนั้นเกิดขึ้นทันที

ตอนนี้คุณรู้ถึงความสำคัญของการแบ่งงานแล้ว ต่อไปก็ดูวิธีทำใน JavaScript ได้เลย

กลยุทธ์การจัดการงาน

คำแนะนำทั่วไปในสถาปัตยกรรมซอฟต์แวร์คือการแบ่งงานออกเป็นฟังก์ชันย่อยๆ ดังนี้

function saveSettings () {
  validateForm();
  showSpinner();
  saveToDatabase();
  updateUI();
  sendAnalytics();
}

ในตัวอย่างนี้ มีฟังก์ชันชื่อ saveSettings() ที่เรียกใช้ฟังก์ชัน 5 รายการเพื่อตรวจสอบแบบฟอร์ม แสดงภาพสปินเนอร์ ส่งข้อมูลไปยังแบ็กเอนด์ของแอปพลิเคชัน อัปเดตอินเทอร์เฟซผู้ใช้ และส่งข้อมูลวิเคราะห์

saveSettings() มีสถาปัตยกรรมที่ดีในแง่แนวคิด หากต้องการแก้ไขข้อบกพร่องของฟังก์ชันใดฟังก์ชันหนึ่งเหล่านี้ คุณสามารถไปยังส่วนต่างๆ ของลําดับชั้นโปรเจ็กต์เพื่อดูว่าฟังก์ชันแต่ละรายการทํางานอย่างไร การแบ่งงานเช่นนี้จะช่วยให้คุณไปยังส่วนต่างๆ ของโปรเจ็กต์และดูแลรักษาโปรเจ็กต์ได้ง่ายขึ้น

อย่างไรก็ตาม ปัญหาที่อาจเกิดขึ้นคือ JavaScript จะไม่เรียกใช้ฟังก์ชันเหล่านี้แต่ละรายการเป็นงานแยกต่างหาก เนื่องจากจะดำเนินการภายในฟังก์ชัน saveSettings() ซึ่งหมายความว่าฟังก์ชันทั้ง 5 รายการจะทำงานเดียวกัน

ฟังก์ชัน saveSettings ตามที่แสดงในเครื่องมือวิเคราะห์ประสิทธิภาพของ Chrome ขณะที่ฟังก์ชันระดับบนสุดเรียกใช้ฟังก์ชันอื่นๆ อีก 5 รายการ งานทั้งหมดจะเกิดขึ้นในภารกิจที่ยาวนานรายการเดียวซึ่งบล็อกเธรดหลัก
ฟังก์ชัน saveSettings() รายการเดียวที่เรียกใช้ฟังก์ชัน 5 รายการ โดยงานดังกล่าวจะเป็นส่วนหนึ่งของงานที่มีขนาดใหญ่เพียงงานเดียว

ในสถานการณ์ที่ดีที่สุด แม้แต่ฟังก์ชันหนึ่งก็สามารถมีส่วนร่วม 50 มิลลิวินาทีหรือมากกว่านั้นให้กับความยาวรวมของงานได้ ในกรณีที่แย่ที่สุด งานเหล่านี้อาจทำงานได้นานขึ้นมาก โดยเฉพาะในอุปกรณ์ที่มีทรัพยากรจํากัด

เลื่อนเวลาการเรียกใช้โค้ดด้วยตนเอง

วิธีหนึ่งที่นักพัฒนาแอปใช้เพื่อแบ่งงานออกเป็นงานเล็กๆ คือการใช้ setTimeout() เทคนิคนี้ช่วยให้คุณส่งฟังก์ชันไปยัง setTimeout() ได้ การดำเนินการนี้จะเลื่อนการเรียกใช้ Callback ไปยังงานแยกต่างหาก แม้ว่าคุณจะระบุระยะหมดเวลาเป็น 0 ก็ตาม

function saveSettings () {
  // Do critical work that is user-visible:
  validateForm();
  showSpinner();
  updateUI();

  // Defer work that isn't user-visible to a separate task:
  setTimeout(() => {
    saveToDatabase();
    sendAnalytics();
  }, 0);
}

การดำเนินการนี้เรียกว่าการให้ผล และเหมาะสําหรับชุดฟังก์ชันที่ต้องทํางานตามลําดับ

อย่างไรก็ตาม รหัสของคุณอาจไม่ได้จัดเรียงแบบนี้เสมอไป เช่น คุณอาจมีข้อมูลจํานวนมากที่ต้องประมวลผลในลูป และงานดังกล่าวอาจใช้เวลานานมากหากมีการทําซ้ำหลายครั้ง

function processData () {
  for (const item of largeDataArray) {
    // Process the individual item here.
  }
}

การใช้ setTimeout() ในที่นี้ทำให้เกิดปัญหาเนื่องจากความสะดวกสบายของนักพัฒนาซอฟต์แวร์ และทั้งอาร์เรย์ของข้อมูลอาจใช้เวลานานมากในการประมวลผล แม้ว่าการวนซ้ำแต่ละครั้งจะทํางานอย่างรวดเร็วก็ตาม เมื่อรวมทั้งหมดเข้าด้วยกันแล้ว setTimeout() ก็ไม่ใช่เครื่องมือที่เหมาะสำหรับงาน อย่างน้อยก็ไม่ใช้วิธีนี้อีก

ใช้ async/await เพื่อสร้างจุดที่มีอัตราผลตอบแทน

คุณสามารถให้สิทธิ์แก่เธรดหลักได้โดยขัดจังหวะคิวงานชั่วคราวเพื่อให้เบราว์เซอร์มีโอกาสทำงานที่สำคัญกว่า เพื่อให้แน่ใจว่างานที่สำคัญซึ่งแสดงต่อผู้ใช้จะดำเนินการก่อนงานที่มีลำดับความสำคัญต่ำกว่า

ตามที่อธิบายไว้ก่อนหน้านี้ setTimeout สามารถใช้เพื่อส่งมอบการควบคุมไปยังเธรดหลัก แต่เพื่อความสะดวกและการอ่านจะง่ายขึ้น คุณสามารถโทรหา setTimeout ภายใน Promise และส่งเมธอด resolve เป็น Callback ได้

function yieldToMain () {
  return new Promise(resolve => {
    setTimeout(resolve, 0);
  });
}

ข้อดีของฟังก์ชัน yieldToMain() คือคุณสามารถawaitฟังก์ชันดังกล่าวในฟังก์ชัน async ใดก็ได้ จากตัวอย่างก่อนหน้านี้ คุณอาจสร้างอาร์เรย์ของฟังก์ชันที่จะเรียกใช้ และส่งคืนไปยังเธรดหลักหลังจากที่แต่ละฟังก์ชันทำงานเสร็จแล้ว ดังนี้

async function saveSettings () {
  // Create an array of functions to run:
  const tasks = [
    validateForm,
    showSpinner,
    saveToDatabase,
    updateUI,
    sendAnalytics
  ]

  // Loop over the tasks:
  while (tasks.length > 0) {
    // Shift the first task off the tasks array:
    const task = tasks.shift();

    // Run the task:
    task();

    // Yield to the main thread:
    await yieldToMain();
  }
}

ผลที่ได้คือตอนนี้งานที่เคยเป็นโมโนลิธถูกแยกออกเป็นงานย่อยๆ

ฟังก์ชัน saveSettings เดียวกันกับที่แสดงในเครื่องมือวิเคราะห์ประสิทธิภาพของ Chrome แต่มี Yielding ผลที่ได้คืองานเดี่ยวๆ ที่เคยถูกแบ่งออกเป็น 5 งาน คือ 1 งานสำหรับแต่ละหน้าที่
ตอนนี้ฟังก์ชัน saveSettings() จะเรียกใช้ฟังก์ชันย่อยเป็นงานแยกต่างหาก

Scheduler API โดยเฉพาะ

setTimeout เป็นวิธีที่มีประสิทธิภาพในการแบ่งงาน แต่ก็ก็มีข้อเสีย คือเมื่อคุณให้เทรดหลักโดยการเลื่อนโค้ดเพื่อทำงานในงานถัดไป งานนั้นจะเพิ่มลงในท้ายของคิว

หากควบคุมโค้ดทั้งหมดในหน้าเว็บ คุณสามารถสร้างตัวตั้งเวลาของคุณเองได้ ซึ่งสามารถจัดลําดับความสําคัญของงานได้ แต่สคริปต์ของบุคคลที่สามจะไม่ใช้ตัวตั้งเวลาของคุณ ด้วยเหตุนี้ คุณจึงไม่สามารถจัดลําดับความสําคัญงานในสภาพแวดล้อมดังกล่าว คุณสามารถแบ่งย่อยหรือส่งต่อการโต้ตอบของผู้ใช้อย่างชัดแจ้งเท่านั้น

การรองรับเบราว์เซอร์

  • Chrome: 94
  • Edge: 94
  • Firefox: อยู่หลังธง
  • Safari: ไม่รองรับ

แหล่งที่มา

Scheduler API มีฟังก์ชัน postTask() ซึ่งช่วยให้กำหนดเวลางานได้ละเอียดยิ่งขึ้น และเป็นวิธีหนึ่งที่ช่วยให้เบราว์เซอร์จัดลำดับความสำคัญของงานเพื่อให้งานที่มีลำดับความสำคัญต่ำทำงานในเธรดหลัก postTask() ใช้การสัญญาและยอมรับการตั้งค่า 1 ใน 3 รายการของ priority ดังนี้

  • 'background' สำหรับงานที่มีลำดับความสำคัญต่ำสุด
  • 'user-visible' สำหรับงานที่มีลำดับความสำคัญปานกลาง ตัวเลือกนี้จะเป็นค่าเริ่มต้นหากไม่ได้ตั้งค่า priority ไว้
  • 'user-blocking' สำหรับงานที่สำคัญซึ่งต้องทำงานที่มีลำดับความสำคัญสูง

มาดูตัวอย่างโค้ดต่อไปนี้ที่ใช้ postTask() API เพื่อเรียกใช้งาน 3 รายการที่มีลำดับความสำคัญสูงสุด และงานที่เหลืออีก 2 รายการที่มีลำดับความสำคัญต่ำสุด

function saveSettings () {
  // Validate the form at high priority
  scheduler.postTask(validateForm, {priority: 'user-blocking'});

  // Show the spinner at high priority:
  scheduler.postTask(showSpinner, {priority: 'user-blocking'});

  // Update the database in the background:
  scheduler.postTask(saveToDatabase, {priority: 'background'});

  // Update the user interface at high priority:
  scheduler.postTask(updateUI, {priority: 'user-blocking'});

  // Send analytics data in the background:
  scheduler.postTask(sendAnalytics, {priority: 'background'});
};

ในส่วนนี้ ระบบจะกำหนดเวลาลำดับความสำคัญของงานในลักษณะที่งานที่มีลำดับความสำคัญสูงกว่าในเบราว์เซอร์ เช่น การโต้ตอบของผู้ใช้ จะได้ทำงานในระหว่างนั้นตามที่จำเป็น

ฟังก์ชัน saveSettings ตามที่แสดงในเครื่องมือวิเคราะห์ประสิทธิภาพของ Chrome แต่ใช้ postTask โดย postTask จะแยกการเรียกใช้ฟังก์ชัน saveSettings แต่ละรายการ และจัดลําดับความสําคัญเพื่อให้การโต้ตอบของผู้ใช้มีโอกาสทํางานโดยไม่ถูกบล็อก
เมื่อเรียกใช้ saveSettings() ฟังก์ชันจะกำหนดเวลาให้กับฟังก์ชันแต่ละรายการโดยใช้ postTask() ระบบจะกำหนดเวลางานที่สำคัญต่อผู้ใช้เป็นลำดับความสำคัญสูง ส่วนงานที่ไม่เกี่ยวข้องกับผู้ใช้จะกำหนดเวลาให้ทำงานในเบื้องหลัง วิธีนี้ช่วยให้การโต้ตอบของผู้ใช้ทํางานได้เร็วขึ้น เนื่องจากมีการแบ่งงานออกเป็นส่วนๆ และจัดลําดับความสําคัญอย่างเหมาะสม

นี่เป็นตัวอย่างที่เข้าใจง่ายของการใช้ postTask() คุณสามารถสร้างอินสแตนซ์ออบเจ็กต์ TaskController ที่แตกต่างกันซึ่งสามารถแชร์ลําดับความสําคัญระหว่างงานต่างๆ รวมถึงสามารถเปลี่ยนลําดับความสําคัญสําหรับอินสแตนซ์ TaskController ต่างๆ ตามต้องการ

ผลตอบแทนในตัวแบบต่อเนื่องโดยใช้ scheduler.yield() API

การรองรับเบราว์เซอร์

  • Chrome: 129
  • ขอบ: 129
  • Firefox: ไม่รองรับ
  • Safari: ไม่รองรับ

แหล่งที่มา

scheduler.yield() เป็น API ที่ออกแบบมาเพื่อส่งมอบชุดข้อความหลักในเบราว์เซอร์โดยเฉพาะ การใช้งานจะคล้ายกับฟังก์ชัน yieldToMain() ที่แสดงก่อนหน้านี้ในคู่มือนี้

async function saveSettings () {
  // Create an array of functions to run:
  const tasks = [
    validateForm,
    showSpinner,
    saveToDatabase,
    updateUI,
    sendAnalytics
  ]

  // Loop over the tasks:
  while (tasks.length > 0) {
    // Shift the first task off the tasks array:
    const task = tasks.shift();

    // Run the task:
    task();

    // Yield to the main thread with the scheduler
    // API's own yielding mechanism:
    await scheduler.yield();
  }
}

ปกติแล้วโค้ดนี้จะคุ้นเคย แต่ใช้ yieldToMain() แทน await scheduler.yield()

แผนภาพ 3 แผนภาพแสดงงานที่ไม่มีเงื่อนไขการให้ผล เงื่อนไขการให้ผล และเงื่อนไขการให้ผลและการดําเนินการต่อ แม้จะไม่ได้ผลตอบแทน ก็จะมีงานยาวๆ อยู่ เมื่อใช้ Yield จะมีงานจำนวนมากขึ้นที่ใช้เวลาสั้นลง แต่อาจถูกขัดจังหวะโดยงานอื่นๆ ที่ไม่เกี่ยวข้อง เมื่อใช้ Yielding และ Continuation จะมีงานจำนวนมากขึ้นที่สั้นลง แต่ลำดับการดำเนินการจะยังคงเดิม
เมื่อใช้ scheduler.yield() การดำเนินการของงานจะเริ่มต้นต่อจากจุดที่หยุดไว้แม้ว่าจะผ่านจุดที่มีผลผลิตแล้วก็ตาม

ข้อดีของ scheduler.yield() คือความต่อเนื่อง ซึ่งหมายความว่าหากคุณหยุดกลางคันระหว่างชุดงาน งานอื่นๆ ที่กำหนดเวลาไว้จะยังคงทำงานตามลำดับเดิมหลังจากจุดหยุด วิธีนี้จะช่วยป้องกันไม่ให้โค้ดจากสคริปต์ของบุคคลที่สามขัดจังหวะลําดับการเรียกใช้โค้ด

ไม่ใช้ isInputPending()

การรองรับเบราว์เซอร์

  • Chrome: 87.
  • Edge: 87
  • Firefox: ไม่รองรับ
  • Safari: ไม่รองรับ

แหล่งที่มา

isInputPending() API ช่วยในการตรวจสอบว่าผู้ใช้ได้พยายามโต้ตอบกับหน้าเว็บหรือไม่ และจะตอบกลับเมื่อมีอินพุตรอดำเนินการเท่านั้น

ซึ่งจะทำให้ JavaScript ดำเนินต่อไปได้หากไม่มีอินพุตที่รอดำเนินการ แทนที่จะแสดงผลที่ท้ายคิวงาน ซึ่งอาจส่งผลให้เกิดประสิทธิภาพที่ดีขึ้นอย่างน่าประทับใจ ตามที่ระบุไว้ในIntent to Ship สำหรับเว็บไซต์ที่อาจไม่ได้แสดงผลในชุดข้อความหลัก

อย่างไรก็ตาม นับตั้งแต่เปิดตัว API ดังกล่าว ความเข้าใจของเราเกี่ยวกับการสร้างรายได้ก็เพิ่มขึ้น โดยเฉพาะเมื่อมีการนำ INP มาใช้ เราไม่แนะนำให้ใช้ API นี้อีกต่อไป และขอแนะนำให้ใช้ Yield ไม่ว่าอินพุตจะรอดำเนินการหรือไม่ก็ตามเนื่องด้วยเหตุผลต่อไปนี้

  • isInputPending() อาจแสดงผล false อย่างไม่ถูกต้องแม้ว่าผู้ใช้จะโต้ตอบในบางกรณีก็ตาม
  • อินพุตไม่ใช่กรณีเดียวที่งานควรให้ผล ภาพเคลื่อนไหวและการอัปเดตอินเทอร์เฟซผู้ใช้ทั่วไปอื่นๆ มีความสำคัญไม่แพ้กับการสร้างหน้าเว็บที่ปรับเปลี่ยนตามอุปกรณ์
  • เราได้เปิดตัว API ที่ให้ผลลัพธ์ที่ครอบคลุมมากขึ้นซึ่งช่วยคลายข้อกังวลเกี่ยวกับผลลัพธ์ เช่น scheduler.postTask() และ scheduler.yield()

บทสรุป

การจัดการงานอาจเป็นเรื่องท้าทาย แต่การทำเช่นนั้นก็ช่วยให้หน้าเว็บตอบสนองต่อการโต้ตอบของผู้ใช้ได้เร็วขึ้น การจัดการและจัดลําดับความสําคัญของงานนั้นไม่มีคําแนะนําเดียว แต่มีหลายเทคนิค เราขอทบทวนสิ่งสำคัญที่ควรพิจารณาเมื่อจัดการงานดังนี้

  • มอบสิทธิ์ให้ชุดข้อความหลักสำหรับงานที่สําคัญซึ่งแสดงต่อผู้ใช้
  • จัดลำดับความสำคัญของงานด้วย postTask()
  • ลองใช้ scheduler.yield()
  • สุดท้าย ให้ทำงานในส่วนต่างๆ ให้น้อยที่สุดเท่าที่จะทำได้

ด้วยเครื่องมือเหล่านี้อย่างน้อย 1 อย่าง คุณจะสามารถจัดโครงสร้างงานในแอปพลิเคชันของคุณ เพื่อให้งานนั้นให้ความสำคัญกับความต้องการของผู้ใช้ ขณะเดียวกันก็ดูแลให้งานที่สำคัญน้อยกว่ายังคงเสร็จสมบูรณ์ ซึ่งจะสร้างประสบการณ์การใช้งานที่ดีขึ้นซึ่งตอบสนองและใช้งานได้ง่ายขึ้น

ขอขอบคุณเป็นพิเศษ Philip Walton ที่ช่วยตรวจสอบคู่มือนี้ทางเทคนิค

ภาพปกจาก Unsplash โดยได้รับความอนุเคราะห์จาก Amirali Mirhashemian