จับการคาดคะเนในเครื่องมือสำหรับนักพัฒนาเว็บใน Chrome: เหตุผลที่ทำให้ยากและวิธีช่วยปรับปรุง

Eric Leese
Eric Leese

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

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

เหตุผลที่การคาดคะเนการจับมีความสำคัญ 

ในเครื่องมือสำหรับนักพัฒนาเว็บใน Chrome คุณจะมีตัวเลือกในการหยุดการเรียกใช้โค้ดชั่วคราวสำหรับข้อยกเว้นที่ตรวจไม่พบเท่านั้น โดยข้ามข้อยกเว้นที่ตรวจพบ 

เครื่องมือสำหรับนักพัฒนาเว็บใน Chrome มีตัวเลือกแยกต่างหากสำหรับการหยุดชั่วคราวเมื่อพบข้อยกเว้นที่จับได้หรือไม่ได้จับ

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

ลองพิจารณาตัวอย่างต่อไปนี้: ควรหยุดโปรแกรมแก้ไขข้อบกพร่องไว้ที่ใด (ดูคำตอบได้ในส่วนถัดไป)

async function inner() {
  throw new Error(); // Should the debugger pause here?
}

async function outer() {
  try {
    const promise = inner();
    // ...
    await promise;
  } catch (e) {
    // ... or should the debugger pause here?
  }
}

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

การคาดการณ์ที่ไม่ถูกต้องทําให้ผู้ใช้ไม่พอใจ

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

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

วิธีการทํางานของโค้ดแบบอะซิงโครนัส

พรอมิส, async และ await และรูปแบบแบบแอซิงโครนัสอื่นๆ อาจทําให้เกิดสถานการณ์ที่ข้อยกเว้นหรือการปฏิเสธอาจใช้เส้นทางการดําเนินการที่กําหนดได้ยากเมื่อมีการยกข้อยกเว้นขึ้นก่อนที่จะมีการจัดการ เนื่องจากระบบอาจไม่รอพรอมต์หรือเพิ่มตัวแฮนเดิลการจับข้อยกเว้นจนกว่าข้อยกเว้นจะเกิดขึ้นแล้ว มาดูตัวอย่างก่อนหน้านี้กัน

async function inner() {
  throw new Error();
}

async function outer() {
  try {
    const promise = inner();
    // ...
    await promise;
  } catch (e) {
    // ...
  }
}

ในตัวอย่างนี้ outer() จะเรียก inner() ก่อน ซึ่งจะแสดงข้อยกเว้นทันที จากข้อมูลนี้ โปรแกรมแก้ไขข้อบกพร่องจะสรุปได้ว่า inner() จะแสดงผลพรอมต์ที่ถูกปฏิเสธ แต่ขณะนี้ไม่มีการดำเนินการใดๆ ที่รอหรือจัดการพรอมต์นั้น โปรแกรมแก้ไขข้อบกพร่องอาจเดาได้ว่า outer() อาจจะรอและเดาว่าจะทำในบล็อก try ปัจจุบัน จึงจัดการกับมันได้ แต่โปรแกรมแก้ไขข้อบกพร่องไม่สามารถแน่ใจได้จนกว่าระบบจะแสดงผล Promise ที่ปฏิเสธและถึงคำสั่ง await ในท้ายที่สุด

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

ใน V8 Promise ของ JavaScript จะแสดงเป็นออบเจ็กต์ที่อยู่ในสถานะใดสถานะหนึ่งต่อไปนี้ นั่นคือ ดำเนินการเสร็จสมบูรณ์ ปฏิเสธ หรือรอดำเนินการ หาก Promise อยู่ในสถานะ "ดำเนินการแล้ว" และคุณเรียกใช้เมธอด .then() ระบบจะสร้าง Promise ที่รอดำเนินการใหม่และกำหนดเวลางานการตอบสนองของ Promise ใหม่ ซึ่งจะเรียกใช้ตัวแฮนเดิล จากนั้นตั้งค่า Promise ให้ดำเนินการแล้วด้วยผลลัพธ์ของตัวแฮนเดิล หรือตั้งค่าให้ปฏิเสธหากตัวแฮนเดิลแสดงข้อยกเว้น การดำเนินการเดียวกันนี้จะเกิดขึ้นหากคุณเรียกใช้เมธอด .catch() ในสัญญาที่ให้ผลลัพธ์เป็นเท็จ ในทางตรงกันข้าม การเรียก .then() ในพรอมต์ที่ถูกปฏิเสธหรือ .catch() ในพรอมต์ที่สำเร็จแล้วจะแสดงผลพรอมต์ในสถานะเดิมและจะไม่เรียกใช้ตัวแฮนเดิล 

พรอมต์ที่รอดำเนินการมีรายการรีแอ็กชัน โดยออบเจ็กต์รีแอ็กชันแต่ละรายการจะมีตัวแฮนเดิลการตอบสนองหรือตัวแฮนเดิลการปฏิเสธ (หรือทั้ง 2 อย่าง) และพรอมต์รีแอ็กชัน ดังนั้นการเรียก .then() ในพรอมต์ที่รอดำเนินการจะเพิ่มรีแอ็กชันที่มีแฮนเดิลที่ดำเนินการแล้ว รวมถึงพรอมต์ใหม่ที่รอดำเนินการสำหรับพรอมต์รีแอ็กชัน ซึ่ง .then() จะแสดงผล การเรียก .catch() จะเพิ่มรีแอ็กชันที่คล้ายกัน แต่จะมีการแฮนเดิลการปฏิเสธ การเรียก .then() ด้วยอาร์กิวเมนต์ 2 รายการจะสร้างการตอบสนองที่มีตัวแฮนเดิลทั้ง 2 รายการ และการเรียก .finally() หรือรอพรอมต์จะเพิ่มการตอบสนองที่มีตัวแฮนเดิล 2 รายการซึ่งเป็นฟังก์ชันในตัวสำหรับการใช้ฟีเจอร์เหล่านี้โดยเฉพาะ

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

ตัวอย่าง

ลองดูโค้ดต่อไปนี้

return new Promise(() => {throw new Error();})
    .then(() => console.log('Never happened'))
    .catch(() => console.log('Caught'));

รหัสนี้อาจไม่ชัดเจนว่าเกี่ยวข้องกับออบเจ็กต์ Promise 3 รายการที่แตกต่างกัน โค้ดข้างต้นเทียบเท่ากับโค้ดต่อไปนี้

const promise1 = new Promise(() => {throw new Error();});
const promise2 = promise1.then(() => console.log('Never happened'));
const promise3 = promise2.catch(() => console.log('Caught'));
return promise3;

ในตัวอย่างนี้ ระบบจะทําตามขั้นตอนต่อไปนี้

  1. เรียกเครื่องมือสร้าง Promise
  2. ระบบจะสร้างPromiseใหม่ซึ่งรอดำเนินการ
  3. ฟังก์ชันนิรนามจะทำงาน
  4. ระบบจะแสดงข้อยกเว้น เมื่อถึงจุดนี้ โปรแกรมแก้ไขข้อบกพร่องจะต้องตัดสินใจว่าจะหยุดหรือไม่
  5. ตัวสร้าง Promise จะจับข้อยกเว้นนี้ แล้วเปลี่ยนสถานะของ Promise เป็น rejected โดยตั้งค่าเป็นข้อผิดพลาดที่แสดง โดยจะแสดงผลพรอมต์นี้ซึ่งจัดเก็บไว้ใน promise1
  6. .then() ไม่ได้ตั้งเวลางานรีแอ็กชันเนื่องจาก promise1 อยู่ในสถานะ rejected แต่ระบบจะแสดงผลลัพธ์เป็น Promise ใหม่ (promise2) ซึ่งอยู่ในสถานะถูกปฏิเสธด้วยข้อผิดพลาดเดียวกัน
  7. .catch() กําหนดเวลางานรีแอ็กชันด้วยตัวแฮนเดิลที่ระบุและสัญญารีแอ็กชันใหม่ซึ่งรอดําเนินการอยู่ ซึ่งจะแสดงผลเป็น promise3 เมื่อถึงจุดนี้ โปรแกรมแก้ไขข้อบกพร่องจะทราบว่าระบบจะจัดการข้อผิดพลาด
  8. เมื่องานรีแอ็กชันทำงาน ตัวแฮนเดิลจะแสดงผลตามปกติและสถานะของ promise3 จะเปลี่ยนเป็น fulfilled

ตัวอย่างถัดไปมีโครงสร้างคล้ายกัน แต่การดําเนินการค่อนข้างแตกต่างกัน

return Promise.resolve()
    .then(() => {throw new Error();})
    .then(() => console.log('Never happened'))
    .catch(() => console.log('Caught'));

ซึ่งเทียบเท่ากับ

const promise1 = Promise.resolve();
const promise2 = promise1.then(() => {throw new Error();});
const promise3 = promise2.then(() => console.log('Never happened'));
const promise4 = promise3.catch(() => console.log('Caught'));
return promise4;

ในตัวอย่างนี้ ระบบจะทําตามขั้นตอนต่อไปนี้

  1. ระบบจะสร้าง Promise ในสถานะ fulfilled และจัดเก็บไว้ใน promise1
  2. ระบบจะกำหนดเวลางานรีแอ็กชันแบบพรอมิสด้วยฟังก์ชันที่ไม่ระบุชื่อรายการแรก และระบบจะแสดงผลพรอมิสรีแอ็กชัน (pending) ของฟังก์ชันดังกล่าวเป็น promise2
  3. ระบบจะเพิ่มรีแอ็กชันลงใน promise2 ด้วยแฮนเดิลที่ดำเนินการเสร็จสมบูรณ์และสัญญารีแอ็กชัน ซึ่งแสดงผลเป็น promise3
  4. ระบบเพิ่มรีแอ็กชันลงใน promise3 ด้วยตัวแฮนเดิลที่ถูกปฏิเสธและพรอมต์รีแอ็กชันอีกรายการ ซึ่งแสดงผลเป็น promise4
  5. ระบบจะเรียกใช้งานที่แสดงความรู้สึกซึ่งกำหนดเวลาไว้ในระยะที่ 2
  6. แฮนเดิลส่งข้อยกเว้น เมื่อถึงจุดนี้ โปรแกรมแก้ไขข้อบกพร่องจะต้องตัดสินใจว่าจะหยุดหรือไม่ ปัจจุบันตัวแฮนเดิลเป็นโค้ด JavaScript เพียงรายการเดียวที่ทำงานอยู่
  7. เนื่องจากงานสิ้นสุดด้วยข้อยกเว้น ระบบจึงตั้งค่าพรอมต์การรีแอ็กชันที่เกี่ยวข้อง (promise2) เป็นสถานะปฏิเสธโดยตั้งค่าเป็นข้อผิดพลาดที่แสดง
  8. เนื่องจาก promise2 มีรีแอ็กชัน 1 รายการ และรีแอ็กชันนั้นไม่มีตัวแฮนเดิลที่ถูกปฏิเสธ ระบบจึงตั้งค่าสัญญารีแอ็กชัน (promise3) เป็น rejected ด้วยข้อผิดพลาดเดียวกัน
  9. เนื่องจาก promise3 มีรีแอ็กชัน 1 รายการ และรีแอ็กชันดังกล่าวมีตัวแฮนเดิลที่ถูกปฏิเสธ ระบบจึงกำหนดเวลางานรีแอ็กชันตามสัญญาให้กับตัวแฮนเดิลดังกล่าวและสัญญารีแอ็กชัน (promise4)
  10. เมื่องานการตอบสนองนั้นทำงาน ตัวแฮนเดิลจะแสดงผลตามปกติและสถานะของ promise4 จะเปลี่ยนเป็น "ดำเนินการแล้ว"

วิธีการคาดการณ์การจับ

แหล่งข้อมูลสำหรับการคาดการณ์การจับปลามี 2 แหล่ง รายการแรกคือสแต็กการเรียกใช้ ซึ่งเหมาะสําหรับข้อยกเว้นแบบซิงค์: โปรแกรมแก้ไขข้อบกพร่องจะเดินสแต็กการเรียกใช้ในลักษณะเดียวกับที่โค้ดการเลิกทำข้อยกเว้นจะทํา และหยุดหากพบเฟรมที่อยู่ในบล็อก try...catch สําหรับพรอมิสหรือข้อยกเว้นที่ถูกปฏิเสธในคอนสตรัคเตอร์พรอมิสหรือในฟังก์ชันแบบแอสซิงโครนัสที่ไม่เคยถูกระงับ โปรแกรมแก้ไขข้อบกพร่องจะอาศัยสแต็กการเรียกใช้ด้วย แต่ในกรณีนี้ การคาดการณ์ของโปรแกรมแก้ไขข้อบกพร่องอาจไม่น่าเชื่อถือในบางกรณี เนื่องจากโค้ดแบบไม่พร้อมกันจะแสดงข้อยกเว้นที่ถูกปฏิเสธแทนที่จะแสดงข้อยกเว้นไปยังตัวแฮนเดิลที่ใกล้ที่สุด และโปรแกรมแก้ไขข้อบกพร่องต้องคาดเดาสิ่งที่ผู้เรียกใช้จะทำกับข้อยกเว้นดังกล่าว

ขั้นแรก โปรแกรมแก้ไขข้อบกพร่องจะถือว่าฟังก์ชันที่ได้รับพรอมต์ที่แสดงผลมีแนวโน้มที่จะแสดงผลพรอมต์นั้นหรือพรอมต์ที่มาจากพรอมต์นั้น เพื่อให้ฟังก์ชันแบบแอสซิงโครนัสที่อยู่สูงขึ้นในกองมีโอกาสรอพรอมต์ดังกล่าว ประการที่ 2 โปรแกรมแก้ไขข้อบกพร่องจะถือว่าหากมีการส่งคืนพรอมิสไปยังฟังก์ชันแบบแอซิงโครนัส โปรแกรมจะรอพรอมิสนั้นในไม่ช้าโดยไม่ต้องเข้าหรือออกจากบล็อก try...catch ก่อน เราไม่รับประกันว่าข้อสันนิษฐานเหล่านี้จะถูกต้อง แต่เพียงพอที่จะทําการคาดการณ์ที่ถูกต้องสําหรับรูปแบบการเขียนโค้ดที่พบบ่อยที่สุดด้วยฟังก์ชันแบบไม่สอดคล้อง ใน Chrome เวอร์ชัน 125 เราได้เพิ่มวิธีการเฮิวริสติกอีกวิธีหนึ่ง โดยโปรแกรมแก้ไขข้อบกพร่องจะตรวจสอบว่าผู้เรียกกำลังจะเรียก .catch() ในค่าที่จะแสดงผล (หรือ .then() ที่มีอาร์กิวเมนต์ 2 รายการ หรือชุดการเรียก .then() หรือ .finally() ตามด้วย .catch() หรือ .then() ที่มีอาร์กิวเมนต์ 2 รายการ) หรือไม่ ในกรณีนี้ โปรแกรมแก้ไขข้อบกพร่องจะถือว่าเมธอดเหล่านี้เป็นเมธอดในสัญญาที่เรากำลังติดตามหรือเมธอดที่เกี่ยวข้องกับสัญญาดังกล่าว จึงจะจับการปฏิเสธได้

แหล่งข้อมูลที่สองคือต้นไม้ของปฏิกิริยาของ Promise โปรแกรมแก้ไขข้อบกพร่องเริ่มต้นด้วยพรอมต์รูท บางครั้งอาจเป็นสัญญาที่เพิ่งเรียกใช้เมธอด reject() กรณีที่พบบ่อยกว่าคือเมื่อมีข้อยกเว้นหรือการปฏิเสธเกิดขึ้นระหว่างงานการตอบสนองของพรอมต์ และดูเหมือนว่าไม่มีรายการใดในสแต็กการเรียกที่จับข้อยกเว้นหรือปฏิเสธดังกล่าว โปรแกรมแก้ไขข้อบกพร่องจะติดตามจากพรอมต์ที่เชื่อมโยงกับการตอบสนอง โปรแกรมแก้ไขข้อบกพร่องจะดูการตอบสนองทั้งหมดในสัญญาที่รอดำเนินการและดูว่ามีการแฮนเดิลการปฏิเสธหรือไม่ หากรีแอ็กชันใดไม่ตรงกัน ระบบจะดูที่สัญญารีแอ็กชันและติดตามจากสัญญานั้นแบบย้อนกลับ หากการตอบสนองทั้งหมดนำไปสู่ตัวแฮนเดิลการปฏิเสธในท้ายที่สุด โปรแกรมแก้ไขข้อบกพร่องจะถือว่ามีการจับการปฏิเสธสัญญา ในกรณีพิเศษบางกรณี เช่น ไม่นับตัวแฮนเดิลการปฏิเสธในตัวสําหรับการเรียก .finally()

แผนภูมิการตอบสนองตามการคาดหวังเป็นแหล่งข้อมูลที่เชื่อถือได้หากมีข้อมูลดังกล่าว ในบางกรณี เช่น การเรียก Promise.reject() หรือในเครื่องมือสร้าง Promise หรือในฟังก์ชันแบบแอสซิงค์ที่ยังไม่ได้รออะไรเลย จะไม่มีปฏิกิริยาต่อการติดตาม และโปรแกรมแก้ไขข้อบกพร่องจะต้องใช้กองคําสั่งการเรียกเท่านั้น ในกรณีอื่นๆ โดยทั่วไปแล้วต้นไม้การตอบสนองของ Promise จะมีตัวแฮนเดิลที่จําเป็นต่อการอนุมานการคาดการณ์การจับข้อยกเว้น แต่อาจมีการเพิ่มตัวแฮนเดิลเพิ่มเติมในภายหลังซึ่งจะเปลี่ยนข้อยกเว้นจากการจับเป็นไม่จับ หรือในทางกลับกัน นอกจากนี้ยังมีการสัญญา เช่น การสัญญาที่ Promise.all/any/race สร้างขึ้น ซึ่งการสัญญาอื่นๆ ในกลุ่มอาจส่งผลต่อวิธีจัดการการปฏิเสธ สําหรับเมธอดเหล่านี้ โปรแกรมแก้ไขข้อบกพร่องจะถือว่าระบบจะส่งต่อการปฏิเสธสัญญาหากสัญญาดังกล่าวยังรอดําเนินการอยู่

มาดูตัวอย่าง 2 ตัวอย่างต่อไปนี้

ตัวอย่างการคาดการณ์การจับ 2 ตัวอย่าง

แม้ว่าตัวอย่างข้อยกเว้นที่พบ 2 รายการนี้ดูคล้ายกัน แต่ต้องใช้ heuristics การคาดการณ์การจับที่แตกต่างกันมาก ในตัวอย่างแรก ระบบจะสร้าง Promise ที่แก้ไขแล้ว จากนั้นกําหนดเวลางานรีแอ็กชันสําหรับ .then() ซึ่งจะแสดงข้อยกเว้น จากนั้นเรียก .catch() เพื่อแนบตัวแฮนเดิลการปฏิเสธไปยัง Promise รีแอ็กชัน เมื่อเรียกใช้งานการตอบสนอง ระบบจะแสดงข้อยกเว้น และต้นไม้การตอบสนองของ Promise จะมีตัวแฮนเดิลการจับ ดังนั้นระบบจะตรวจพบว่ามีการจับข้อยกเว้น ในตัวอย่างที่ 2 ระบบจะปฏิเสธ Promise ทันทีก่อนที่จะเรียกใช้โค้ดเพื่อเพิ่มตัวแฮนเดิลการจับ ดังนั้นจึงไม่มีตัวแฮนเดิลการปฏิเสธในต้นไม้การตอบสนองของ Promise โปรแกรมแก้ไขข้อบกพร่องต้องดูสแต็กการเรียก แต่ไม่มีบล็อก try...catch ด้วย โปรแกรมแก้ไขข้อบกพร่องจะสแกนตำแหน่งก่อนหน้าตำแหน่งปัจจุบันในโค้ดเพื่อค้นหาการเรียกใช้ .catch() และคาดการณ์ว่าระบบจะจัดการการปฏิเสธในท้ายที่สุด เพื่อคาดการณ์ได้อย่างถูกต้อง

สรุป

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

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

ขอขอบคุณ

ขอขอบคุณ Sofia Emelianova และ Jecelyn Yeen เป็นอย่างยิ่งสำหรับความช่วยเหลืออันล้ำค่าในการแก้ไขโพสต์นี้