README นี้มีข้อมูลที่ฉันได้เรียนรู้มานานหลายปีเกี่ยวกับการจัดการกับข้อผิดพลาดของ JavaScript การรายงานข้อผิดพลาดไปยังเซิร์ฟเวอร์ และการนำทางผ่านข้อบกพร่องมากมายที่อาจทำให้ทั้งหมดนี้ยากจริงๆ เบราว์เซอร์ได้รับการปรับปรุงในส่วนนี้ แต่ยังเหลือพื้นที่เหลือให้ปรับปรุงเพื่อให้แน่ใจว่าแอปพลิเคชันทั้งหมดสามารถจัดการกับข้อผิดพลาดที่เกิดขึ้นได้อย่างมีสติและเหมาะสม
กรณีทดสอบสำหรับเนื้อหาที่พบในคู่มือนี้มีอยู่ที่ https://mknichel.github.io/javascript-errors/
สารบัญ
การแนะนำ
กายวิภาคของข้อผิดพลาด JavaScript
การสร้างข้อผิดพลาด JavaScript
ข้อความแสดงข้อผิดพลาด
รูปแบบการติดตามสแต็ก
การจับข้อผิดพลาด JavaScript
หน้าต่าง onerror
ลอง/จับ
จุดเข้าที่ได้รับการคุ้มครอง
สัญญา
คนทำงานเว็บ
ส่วนขยายของ Chrome
การตรวจจับ การรายงาน และการแก้ไขข้อผิดพลาดเป็นส่วนสำคัญของแอปพลิเคชันใดๆ เพื่อให้มั่นใจในความสมบูรณ์และความเสถียรของแอปพลิเคชัน เนื่องจากโค้ด JavaScript ยังถูกดำเนินการบนไคลเอนต์และในสภาพแวดล้อมเบราว์เซอร์ที่แตกต่างกัน การควบคุมข้อผิดพลาด JS จากแอปพลิเคชันของคุณก็อาจเป็นเรื่องยากเช่นกัน ไม่มีข้อกำหนดเว็บอย่างเป็นทางการสำหรับวิธีรายงานข้อผิดพลาด JS ซึ่งทำให้เกิดความแตกต่างในการใช้งานเบราว์เซอร์แต่ละตัว นอกจากนี้ ยังมีข้อบกพร่องมากมายในการใช้งานข้อผิดพลาด JavaScript ของเบราว์เซอร์ ซึ่งทำให้การดำเนินการนี้ยากยิ่งขึ้น หน้านี้อธิบายแง่มุมต่างๆ ของข้อผิดพลาด JS เพื่อให้นักพัฒนาในอนาคตสามารถจัดการกับข้อผิดพลาดได้ดีขึ้น และหวังว่าเบราว์เซอร์จะมาบรรจบกันในโซลูชันมาตรฐาน
ข้อผิดพลาด JavaScript ประกอบด้วยสองส่วนหลัก: ข้อความแสดงข้อผิดพลาด และ การติดตามสแต็ก ข้อความแสดงข้อผิดพลาดคือสตริงที่อธิบายสิ่งที่ผิดพลาด และการติดตามสแต็กจะอธิบายว่าข้อผิดพลาดเกิดขึ้นที่ใดในโค้ด ข้อผิดพลาด JS สามารถสร้างขึ้นโดยเบราว์เซอร์เองหรือส่งโดยรหัสแอปพลิเคชัน
เบราว์เซอร์สามารถส่งข้อผิดพลาด JS ได้เมื่อโค้ดบางส่วนทำงานไม่ถูกต้อง หรือสามารถส่งด้วยโค้ดโดยตรงก็ได้
ตัวอย่างเช่น:
var a = 3;a();
ในตัวอย่างนี้ ตัวแปรที่เป็นตัวเลขจริงๆ ไม่สามารถเรียกใช้เป็นฟังก์ชันได้ เบราว์เซอร์จะแสดงข้อผิดพลาด เช่น TypeError: a is not a function
ที่มีการติดตามสแต็กที่ชี้ไปที่บรรทัดของโค้ดนั้น
นักพัฒนาอาจต้องการส่งข้อผิดพลาดในโค้ดบางส่วนหากไม่ตรงตามเงื่อนไขเบื้องต้นบางประการ ตัวอย่างเช่น
ถ้า (!checkPrecondition()) { โยนข้อผิดพลาดใหม่ ("ไม่ตรงตามเงื่อนไขเบื้องต้น!");}
ในกรณีนี้ ข้อผิดพลาดจะเป็น Error: Doesn't meet precondition!
- ข้อผิดพลาดนี้จะมีการติดตามสแต็กที่ชี้ไปยังบรรทัดที่เหมาะสมด้วย ข้อผิดพลาดที่เกิดจากเบราว์เซอร์และรหัสแอปพลิเคชันสามารถจัดการได้เหมือนกัน
มีหลายวิธีที่นักพัฒนาสามารถส่งข้อผิดพลาดใน JavaScript:
throw new Error('Problem description.')
throw Error('Problem description.')
<-- เทียบเท่ากับอันแรก
throw 'Problem description.'
<-- แย่
throw null
<-- แย่ยิ่งกว่านั้นอีก
ไม่แนะนำให้โยนสตริงหรือค่าว่าง เนื่องจากเบราว์เซอร์จะไม่แนบการติดตามสแต็กกับข้อผิดพลาดนั้น โดยสูญเสียบริบทของตำแหน่งที่เกิดข้อผิดพลาดในโค้ด วิธีที่ดีที่สุดคือโยนอ็อบเจ็กต์ Error จริง ซึ่งจะมีข้อความแสดงข้อผิดพลาดตลอดจนการติดตามสแต็กที่ชี้ไปยังบรรทัดโค้ดด้านขวาที่เกิดข้อผิดพลาด
แต่ละเบราว์เซอร์มีชุดข้อความของตัวเองที่ใช้สำหรับข้อยกเว้นในตัว เช่น ตัวอย่างข้างต้นสำหรับการพยายามเรียกใช้ฟังก์ชันที่ไม่ใช่ เบราว์เซอร์จะพยายามใช้ข้อความเดียวกัน แต่เนื่องจากไม่มีข้อมูลจำเพาะ จึงไม่รับประกัน ตัวอย่างเช่น การใช้ทั้ง Chrome และ Firefox {0} is not a function
สำหรับตัวอย่างข้างต้น ในขณะที่ IE11 จะรายงาน Function expected
(โดยเฉพาะอย่างยิ่งโดยไม่รายงานว่าพยายามเรียกตัวแปรใด)
อย่างไรก็ตาม เบราว์เซอร์มักจะมีความแตกต่างกันบ่อยครั้งเช่นกัน เมื่อมีคำสั่งเริ่มต้นหลายรายการในคำสั่ง switch
Chrome จะส่ง "More than one default clause in switch statement"
ในขณะที่ Firefox จะรายงาน "more than one switch default"
เมื่อมีการเพิ่มคุณสมบัติใหม่ลงในเว็บ ข้อความแสดงข้อผิดพลาดเหล่านี้จะต้องได้รับการอัปเดต ความแตกต่างเหล่านี้อาจเกิดขึ้นได้ในภายหลังเมื่อคุณพยายามจัดการกับข้อผิดพลาดที่รายงานจากโค้ดที่สร้างความสับสน
คุณสามารถค้นหาเทมเพลตที่เบราว์เซอร์ใช้สำหรับข้อความแสดงข้อผิดพลาดได้ที่:
ไฟร์ฟอกซ์ - http://mxr.mozilla.org/mozilla1.9.1/source/js/src/js.msg
Chrome - https://code.google.com/p/v8/source/browse/branches/bleeding_edge/src/messages.js
อินเทอร์เน็ต Explorer - https://github.com/Microsoft/ChakraCore/blob/4e4d4f00f11b2ded23d1885e85fc26fcc96555da/lib/Parser/rterrors.h
เบราว์เซอร์จะสร้างข้อความแสดงข้อผิดพลาดที่แตกต่างกันสำหรับข้อยกเว้นบางประการ
การติดตามสแต็กคือคำอธิบายว่าข้อผิดพลาดเกิดขึ้นที่ใดในโค้ด ประกอบด้วยชุดของเฟรม โดยแต่ละเฟรมจะอธิบายบรรทัดเฉพาะในโค้ด เฟรมบนสุดคือตำแหน่งที่เกิดข้อผิดพลาด ในขณะที่เฟรมต่อมาคือสแต็กการเรียกใช้ฟังก์ชัน หรือวิธีดำเนินการโค้ดเพื่อไปยังจุดที่เกิดข้อผิดพลาด เนื่องจากจาวาสคริปต์มักจะถูกแบ่งส่วนและย่อเล็กสุด จึงเป็นสิ่งสำคัญที่จะต้องมีหมายเลขคอลัมน์ เพื่อให้สามารถระบุตำแหน่งคำสั่งที่ตรงกันได้เมื่อบรรทัดที่กำหนดมีคำสั่งจำนวนมาก
การติดตามสแต็กพื้นฐานใน Chrome มีลักษณะดังนี้:
at throwError (http://mknichel.github.io/javascript-errors/throw-error-basic.html:8:9) at http://mknichel.github.io/javascript-errors/throw-error-basic.html:12:3
แต่ละเฟรมสแต็กประกอบด้วยชื่อฟังก์ชัน (หากมีและโค้ดไม่ได้ถูกดำเนินการในขอบเขตส่วนกลาง) สคริปต์ที่มาจาก และหมายเลขบรรทัดและคอลัมน์ของโค้ด
ขออภัย ไม่มีมาตรฐานสำหรับรูปแบบการติดตามสแต็ก ดังนั้นรูปแบบจึงแตกต่างกันไปตามเบราว์เซอร์
การติดตามสแต็กของ Microsoft Edge และ IE 11 มีลักษณะคล้ายกับของ Chrome ยกเว้นว่าจะแสดงรหัสสากลอย่างชัดเจน:
at throwError (http://mknichel.github.io/javascript-errors/throw-error-basic.html:8:3) at Global code (http://mknichel.github.io/javascript-errors/throw-error-basic.html:12:3)
การติดตามสแต็กของ Firefox ดูเหมือนว่า:
throwError@http://mknichel.github.io/javascript-errors/throw-error-basic.html:8:9 @http://mknichel.github.io/javascript-errors/throw-error-basic.html:12:3
รูปแบบของ Safari คล้ายกับรูปแบบของ Firefox แต่ก็แตกต่างออกไปเล็กน้อย:
throwError@http://mknichel.github.io/javascript-errors/throw-error-basic.html:8:18 global code@http://mknichel.github.io/javascript-errors/throw-error-basic.html:12:13
มีข้อมูลพื้นฐานเหมือนกัน แต่รูปแบบจะแตกต่างกัน
โปรดทราบว่าในตัวอย่าง Safari นอกเหนือจากรูปแบบที่แตกต่างจาก Chrome แล้ว หมายเลขคอลัมน์ยังแตกต่างจากทั้ง Chrome และ Firefox หมายเลขคอลัมน์ยังสามารถเบี่ยงเบนได้มากขึ้นในสถานการณ์ข้อผิดพลาดต่างๆ - ตัวอย่างเช่นในโค้ด (function namedFunction() { throwError(); })();
Chrome จะรายงานคอลัมน์สำหรับการเรียกใช้ฟังก์ชัน throwError()
ในขณะที่ IE11 รายงานหมายเลขคอลัมน์เป็นจุดเริ่มต้นของสตริง ความแตกต่างเหล่านี้จะกลับมามีบทบาทอีกครั้งในภายหลัง เมื่อเซิร์ฟเวอร์จำเป็นต้องแยกวิเคราะห์การติดตามสแต็กเพื่อหาข้อผิดพลาดที่รายงาน และถอดรหัสซอร์สโค้ดที่สร้างความสับสนให้กับสแต็กเทรซที่สร้างความสับสน
ดู https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error/Stack สำหรับข้อมูลเพิ่มเติมเกี่ยวกับคุณสมบัติสแต็กของข้อผิดพลาด เมื่อเข้าถึงคุณสมบัติ Error.stack Chrome จะรวมข้อความแสดงข้อผิดพลาดเป็นส่วนหนึ่งของสแต็ก แต่ Safari 10+ ไม่มี
รูปแบบของการติดตามสแต็กจะแตกต่างกันไปตามเบราว์เซอร์ทั้งในรูปแบบและหมายเลขคอลัมน์ที่ใช้
หากเจาะลึกลงไปอีก มีความแตกต่างมากมายในการซ้อนรูปแบบการติดตามซึ่งจะกล่าวถึงในส่วนด้านล่าง
ตามค่าเริ่มต้น ฟังก์ชันที่ไม่ระบุชื่อจะไม่มีชื่อและปรากฏเป็นสตริงว่างหรือ "ฟังก์ชันที่ไม่ระบุชื่อ" ในชื่อฟังก์ชันในการติดตามสแต็ก (ขึ้นอยู่กับเบราว์เซอร์) เพื่อปรับปรุงการดีบัก คุณควรเพิ่มชื่อให้กับฟังก์ชันทั้งหมดเพื่อให้แน่ใจว่าจะปรากฏในเฟรมสแต็ก วิธีที่ง่ายที่สุดในการทำเช่นนี้คือตรวจสอบให้แน่ใจว่ามีการระบุฟังก์ชันที่ไม่ระบุชื่อด้วยชื่อ แม้ว่าชื่อนั้นจะไม่ได้ใช้ที่อื่นก็ตาม ตัวอย่างเช่น:
setTimeout(ชื่อฟังก์ชันOfTheAnonymousFunction() { ... }, 0);
สิ่งนี้จะทำให้การติดตามสแต็กเปลี่ยนจาก:
at http://mknichel.github.io/javascript-errors/javascript-errors.js:125:17
ถึง
at nameOfTheAnonymousFunction (http://mknichel.github.io/javascript-errors/javascript-errors.js:121:31)
ใน Safari สิ่งนี้จะไปจาก:
https://mknichel.github.io/javascript-errors/javascript-errors.js:175:27
ถึง
nameOfTheAnonymousFunction@https://mknichel.github.io/javascript-errors/javascript-errors.js:171:41
วิธีการนี้ช่วยให้แน่ใจว่า nameOfTheAnonymousFunction
ปรากฏในเฟรมของโค้ดใดๆ จากภายในฟังก์ชันนั้น ทำให้การดีบักง่ายขึ้นมาก ดูhttp://www.html5rocks.com/en/tutorials/developertools/async-call-stack/#toc-debugging-tipsสำหรับข้อมูลเพิ่มเติม
เบราว์เซอร์จะใช้ชื่อของตัวแปรหรือคุณสมบัติที่กำหนดฟังก์ชันให้ หากฟังก์ชันนั้นไม่มีชื่อ ตัวอย่างเช่นใน
var fnVariableName = function() { ... };
เบราว์เซอร์จะใช้ fnVariableName
เป็นชื่อของฟังก์ชันในการติดตามสแต็ก
at throwError (http://mknichel.github.io/javascript-errors/javascript-errors.js:27:9) at fnVariableName (http://mknichel.github.io/javascript-errors/javascript-errors.js:169:37)
ยิ่งไปกว่านั้น หากตัวแปรนี้ถูกกำหนดไว้ภายในฟังก์ชันอื่น เบราว์เซอร์ทั้งหมดจะใช้เพียงชื่อของตัวแปรเป็นชื่อของฟังก์ชันในการติดตามสแต็ก ยกเว้น Firefox ซึ่งจะใช้รูปแบบอื่นที่เชื่อมชื่อของ ฟังก์ชันภายนอกที่มีชื่อของตัวแปรภายใน ตัวอย่าง:
ฟังก์ชั่น ThrowErrorFromInnerFunctionAssignedToVariable() { var fnVariableName = function() { โยนข้อผิดพลาดใหม่ ("foo"); - fnVariableName();}
จะผลิตใน Firefox:
throwErrorFromInnerFunctionAssignedToVariable/fnVariableName@http://mknichel.github.io/javascript-errors/javascript-errors.js:169:37
ในเบราว์เซอร์อื่น สิ่งนี้จะมีลักษณะดังนี้:
at fnVariableName (http://mknichel.github.io/javascript-errors/javascript-errors.js:169:37)
Firefox ใช้ข้อความเฟรมสแต็กที่แตกต่างกันสำหรับฟังก์ชันที่กำหนดไว้ภายในฟังก์ชันอื่น
ชื่อที่แสดงของฟังก์ชันสามารถตั้งค่าได้ด้วยคุณสมบัติ displayName
ในเบราว์เซอร์หลักๆ ทั้งหมด ยกเว้น IE11 ในเบราว์เซอร์เหล่านี้ displayName จะปรากฏในดีบักเกอร์ devtools แต่ในเบราว์เซอร์ทั้งหมดยกเว้น Safari จะ ไม่ ใช้ในการติดตามสแต็กข้อผิดพลาด (Safari แตกต่างจากที่เหลือโดยใช้ชื่อจอแสดงผลในการติดตามสแต็กที่เกี่ยวข้องกับข้อผิดพลาด)
var someFunction = function() {};someFunction.displayName = " # คำอธิบายฟังก์ชันที่ยาวขึ้น";
ไม่มีข้อกำหนดอย่างเป็นทางการสำหรับคุณสมบัติ displayName แต่เบราว์เซอร์หลักๆ ทั้งหมดรองรับ ดู https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/displayName และ http://www.alertdebugging.com/2009/04/29/building-a-better -javascript-profiler-with-webkit/ สำหรับข้อมูลเพิ่มเติมเกี่ยวกับ displayName
IE11 ไม่รองรับคุณสมบัติ displayName
Safari ใช้คุณสมบัติ displayName เป็นชื่อสัญลักษณ์ในการติดตามสแต็กข้อผิดพลาด
หากมีการรายงานข้อผิดพลาดโดยไม่มีการติดตามสแต็ก (ดูรายละเอียดเพิ่มเติมเมื่อสิ่งนี้จะเกิดขึ้นด้านล่าง) ก็เป็นไปได้ที่จะบันทึกการติดตามสแต็กโดยทางโปรแกรม
ใน Chrome สิ่งนี้ทำได้ง่ายมากโดยใช้ Error.captureStackTrace
API ดู https://github.com/v8/v8/wiki/Stack%20Trace%20API สำหรับข้อมูลเพิ่มเติมเกี่ยวกับการใช้ API นี้
ตัวอย่างเช่น:
ฟังก์ชั่นละเลยThisFunctionInStackTrace() { var err = ข้อผิดพลาดใหม่ (); Error.captureStackTrace (ผิดพลาด, ละเว้นThisFunctionInStackTrace); กลับข้อผิดพลาด.สแต็ค;}
ในเบราว์เซอร์อื่นๆ การติดตามสแต็กสามารถรวบรวมได้โดยการสร้างข้อผิดพลาดใหม่และการเข้าถึงคุณสมบัติสแต็กของออบเจ็กต์นั้น:
var err = ข้อผิดพลาดใหม่ (''); return err.stack;
อย่างไรก็ตาม IE10 จะเติมการติดตามสแต็กเฉพาะเมื่อเกิดข้อผิดพลาดจริงเท่านั้น:
พยายาม { โยนข้อผิดพลาดใหม่ ('');} catch (e) { ส่งคืน e.stack;}
หากวิธีการเหล่านี้ไม่ได้ผล คุณสามารถสร้างการติดตามสแต็กคร่าวๆ โดยไม่มีหมายเลขบรรทัดหรือคอลัมน์ได้โดยการวนซ้ำอ็อบเจ็กต์ arguments.callee.caller
แต่วิธีนี้จะไม่ทำงานในโหมดเข้มงวด ES5 และไม่ใช่แนวทางที่แนะนำ
เป็นเรื่องปกติมากที่จุดอะซิงโครนัสจะถูกแทรกลงในโค้ด JavaScript เช่น เมื่อโค้ดใช้ setTimeout
หรือผ่านการใช้ Promises จุดเข้าแบบอะซิงก์เหล่านี้อาจทำให้เกิดปัญหาสำหรับการติดตามสแต็ก เนื่องจากทำให้เกิดบริบทการดำเนินการใหม่ในรูปแบบและการติดตามสแต็กเริ่มต้นใหม่อีกครั้ง
Chrome DevTools รองรับการติดตามสแต็กแบบอะซิงก์ หรืออีกนัยหนึ่งคือทำให้แน่ใจว่าสแต็กเทรซของข้อผิดพลาดจะแสดงเฟรมที่เกิดขึ้นก่อนที่จะมีการนำจุดอะซิงก์มาใช้ด้วย ด้วยการใช้ setTimeout สิ่งนี้จะบันทึกว่าใครเป็นผู้เรียกใช้ฟังก์ชัน setTimeout ที่ทำให้เกิดข้อผิดพลาดในที่สุด ดูhttp://www.html5rocks.com/en/tutorials/developertools/async-call-stack/สำหรับข้อมูลเพิ่มเติม
การติดตามสแต็กแบบอะซิงก์จะมีลักษณะดังนี้:
throwError @ throw-error.js:2 setTimeout (async) throwErrorAsync @ throw-error.js:10 (anonymous function) @ throw-error-basic.html:14
ขณะนี้การติดตามสแต็ก Async ได้รับการสนับสนุนเฉพาะใน Chrome DevTools เท่านั้นสำหรับข้อยกเว้นที่เกิดขึ้นเมื่อเปิด DevTools เท่านั้น การติดตามสแต็กที่เข้าถึงได้จากออบเจ็กต์ข้อผิดพลาดในโค้ดจะ ไม่มี การติดตามสแต็กแบบอะซิงก์เป็นส่วนหนึ่งของการติดตามสแต็ก
ในบางกรณี เป็นไปได้ที่จะเติมโพลีฟิลอะซิงก์สแต็กเทรซได้ แต่อาจทำให้ประสิทธิภาพลดลงอย่างมากสำหรับแอปพลิเคชันของคุณ เนื่องจากการจับสแต็กเทรซนั้นไม่ได้ราคาถูก
เฉพาะ Chrome DevTools เท่านั้นที่รองรับการติดตามสแต็กอะซิงก์
การติดตามสแต็กสำหรับโค้ดที่ได้รับการประเมินหรืออินไลน์ในหน้า HTML จะใช้ URL ของเพจและหมายเลขบรรทัด/คอลัมน์สำหรับโค้ดที่ดำเนินการ
ตัวอย่างเช่น:
at throwError (http://mknichel.github.io/javascript-errors/throw-error-basic.html:8:9) at http://mknichel.github.io/javascript-errors/throw-error-basic.html:12:3
หากสคริปต์เหล่านี้มาจากสคริปต์ที่อินไลน์เพื่อเหตุผลในการเพิ่มประสิทธิภาพจริงๆ แล้วหมายเลข URL บรรทัดและคอลัมน์จะผิด เพื่อแก้ไขปัญหานี้ Chrome และ Firefox สนับสนุน //# sourceURL=
คำอธิบายประกอบ (Safari, Edge และ IE ไม่รองรับ) URL ที่ระบุในคำอธิบายประกอบนี้จะถูกใช้เป็น URL สำหรับการติดตามสแต็กทั้งหมด และหมายเลขบรรทัดและคอลัมน์จะถูกคำนวณโดยสัมพันธ์กับจุดเริ่มต้นของแท็ก แทนเอกสาร HTML สำหรับข้อผิดพลาดเดียวกันกับข้างต้น การใช้คำอธิบายประกอบ sourceURL ที่มีค่า "inline.js" จะสร้างการติดตามสแต็กที่มีลักษณะดังนี้:
at throwError (http://mknichel.github.io/javascript-errors/inline.js:8:9) at http://mknichel.github.io/javascript-errors/inline.js:12:3
นี่เป็นเทคนิคที่มีประโยชน์มากเพื่อให้แน่ใจว่าการติดตามสแต็กยังคงถูกต้องแม้ว่าจะใช้สคริปต์อินไลน์และ eval ก็ตาม
http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl อธิบายคำอธิบายประกอบ sourceURL โดยละเอียดเพิ่มเติม
Safari, Edge และ IE ไม่รองรับคำอธิบายประกอบ URL ต้นทางสำหรับการตั้งชื่อสคริปต์อินไลน์และการประเมินค่า หากคุณใช้สคริปต์อินไลน์ใน IE หรือ Safari และทำให้โค้ดของคุณสับสน คุณจะไม่สามารถถอดรหัสข้อผิดพลาดที่มาจากสคริปต์เหล่านั้นได้
จนถึง Chrome 42 Chrome ไม่ได้คำนวณหมายเลขบรรทัดอย่างถูกต้องสำหรับสคริปต์อินไลน์ที่ใช้คำอธิบายประกอบ sourceURL ดู https://bugs.chromium.org/p/v8/issues/detail?id=3920 สำหรับข้อมูลเพิ่มเติม
หมายเลขบรรทัดสำหรับสแต็กเฟรมจากสคริปต์อินไลน์ไม่ถูกต้องเมื่อมีการใช้คำอธิบายประกอบ sourceURL เนื่องจากสัมพันธ์กับจุดเริ่มต้นของเอกสาร HTML แทนที่จะเป็นจุดเริ่มต้นของแท็กสคริปต์อินไลน์ (ทำให้ไม่สามารถถอดรหัสลดความสับสนที่ถูกต้องได้) https://code.google.com/p/chromium/issues/detail?id=578269
สำหรับโค้ดที่ใช้ eval จะมีความแตกต่างอื่นๆ ในการติดตามสแต็ก นอกเหนือจากว่าจะใช้คำอธิบายประกอบ sourceURL หรือไม่ ใน Chrome การติดตามสแต็กจากคำสั่งที่ใช้ใน eval อาจมีลักษณะดังนี้:
Error: Error from eval at evaledFunction (eval at evalError (http://mknichel.github.io/javascript-errors/javascript-errors.js:137:3),:1:36) at eval (eval at evalError (http://mknichel.github.io/javascript-errors/javascript-errors.js:137:3), :1:68) at evalError (http://mknichel.github.io/javascript-errors/javascript-errors.js:137:3)
ใน MS Edge และ IE11 สิ่งนี้จะมีลักษณะดังนี้:
Error from eval at evaledFunction (eval code:1:30) at eval code (eval code:1:2) at evalError (http://mknichel.github.io/javascript-errors/javascript-errors.js:137:3)
ในซาฟารี:
Error from eval evaledFunction eval code eval@[native code] evalError@http://mknichel.github.io/javascript-errors/javascript-errors.js:137:7
และใน Firefox:
Error from eval evaledFunction@http://mknichel.github.io/javascript-errors/javascript-errors.js line 137 > eval:1:36 @http://mknichel.github.io/javascript-errors/javascript-errors.js line 137 > eval:1:11 evalError@http://mknichel.github.io/javascript-errors/javascript-errors.js:137:3
ความแตกต่างเหล่านี้อาจทำให้แยกวิเคราะห์โค้ด eval เหมือนกันในทุกเบราว์เซอร์ได้ยาก
แต่ละเบราว์เซอร์ใช้รูปแบบการติดตามสแต็กที่แตกต่างกันสำหรับข้อผิดพลาดที่เกิดขึ้นภายใน eval
คุณสามารถเรียกโค้ด JavaScript ของคุณได้โดยตรงจากโค้ดเนทีฟ Array.prototype.forEach
เป็นตัวอย่างที่ดี - คุณส่งฟังก์ชันไปที่ forEach
และเอ็นจิ้น JS จะเรียกใช้ฟังก์ชันนั้นให้คุณ
ฟังก์ชั่น ThrowErrorWithNativeFrame() { วาร์ arr = [0, 1, 2, 3]; arr.forEach (ฟังก์ชันชื่อ Fn (ค่า) {throwError (); -
ซึ่งสร้างการติดตามสแต็กที่แตกต่างกันในเบราว์เซอร์ที่แตกต่างกัน Chrome และ Safari จะเพิ่มชื่อของฟังก์ชันดั้งเดิมต่อท้ายการติดตามสแต็กเป็นเฟรมที่แยกจากกัน เช่น:
(Chrome) at namedFn (http://mknichel.github.io/javascript-errors/javascript-errors.js:153:5) at Array.forEach (native) at throwErrorWithNativeFrame (http://mknichel.github.io/javascript-errors/javascript-errors.js:152:7) (Safari) namedFn@http://mknichel.github.io/javascript-errors/javascript-errors.js:153:15 forEach@[native code] throwErrorWithNativeFrame@http://mknichel.github.io/javascript-errors/javascript-errors.js:152:14 (Edge) at namedFn (http://mknichel.github.io/javascript-errors/javascript-errors.js:153:5) at Array.prototype.forEach (native code) at throwErrorWithNativeFrame (http://mknichel.github.io/javascript-errors/javascript-errors.js:152:7)
อย่างไรก็ตาม Firefox และ IE11 ไม่ แสดงว่า forEach
ถูกเรียกเป็นส่วนหนึ่งของสแต็ก:
namedFn@http://mknichel.github.io/javascript-errors/javascript-errors.js:153:5 throwErrorWithNativeFrame@http://mknichel.github.io/javascript-errors/javascript-errors.js:152:3
เบราว์เซอร์บางตัวรวมเฟรมโค้ดดั้งเดิมไว้ในการติดตามสแต็ก ในขณะที่เบราว์เซอร์บางตัวไม่มี
เพื่อตรวจสอบว่าแอปพลิเคชันของคุณมีข้อผิดพลาด โค้ดบางตัวจะต้องสามารถตรวจจับข้อผิดพลาดนั้นและรายงานเกี่ยวกับข้อผิดพลาดนั้นได้ มีเทคนิคหลายประการในการตรวจจับข้อผิดพลาด แต่ละเทคนิคมีข้อดีและข้อเสีย
window.onerror
เป็นหนึ่งในวิธีที่ง่ายและดีที่สุดในการเริ่มต้นตรวจจับข้อผิดพลาด ด้วยการกำหนด window.onerror
ให้กับฟังก์ชัน ข้อผิดพลาดใดๆ ที่ไม่ได้ถูกตรวจจับโดยส่วนอื่นของแอปพลิเคชันจะถูกรายงานไปยังฟังก์ชันนี้ พร้อมด้วยข้อมูลบางอย่างเกี่ยวกับข้อผิดพลาด ตัวอย่างเช่น:
window.onerror = function(msg, url, line, col, err) { console.log('แอปพลิเคชันพบข้อผิดพลาด: ' + msg); console.log('การติดตามสแต็ก: ' + err.stack);}
https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers/onerror อธิบายรายละเอียดเพิ่มเติมเกี่ยวกับเรื่องนี้
ในอดีต แนวทางนี้มีปัญหาบางประการ:
ไม่มีวัตถุข้อผิดพลาดที่ให้มา
อาร์กิวเมนต์ที่ 5 ของฟังก์ชัน window.onerror
ควรเป็นอ็อบเจ็กต์ Error สิ่งนี้ถูกเพิ่มเข้าไปในข้อมูลจำเพาะ WHATWG ในปี 2013: https://html.spec.whatwg.org/multipage/webappapis.html#errorevent ขณะนี้ Chrome, Firefox และ IE11 จัดเตรียมออบเจ็กต์ข้อผิดพลาดอย่างถูกต้อง (พร้อมกับคุณสมบัติสแต็กวิกฤต) แต่ Safari, MS Edge และ IE10 ไม่มี สิ่งนี้ใช้ได้กับ Firefox ตั้งแต่ Firefox 14 (https://bugzilla.mozilla.org/show_bug.cgi?id=355430) และใน Chrome ตั้งแต่ปลายปี 2013 (https://mikewest.org/2013/08/debugging-runtime-errors -with-window-onerror, https://code.google.com/p/chromium/issues/detail?id=147127) Safari 10 เปิดตัวการรองรับวัตถุ Error ใน window.onerror
Safari (เวอร์ชันต่ำกว่า 10), MS Edge และ IE10 ไม่รองรับอ็อบเจ็กต์ข้อผิดพลาดที่มีการติดตามสแต็กใน window.onerror
การฆ่าเชื้อข้ามโดเมน
ใน Chrome ข้อผิดพลาดที่มาจากโดเมนอื่นในตัวจัดการ window.onerror จะถูกกำจัดเป็น "ข้อผิดพลาดของสคริปต์", "", 0 โดยทั่วไปนี่เป็นเรื่องปกติหากคุณไม่ต้องการประมวลผลข้อผิดพลาดจริงๆ หากข้อผิดพลาดนั้นมาจาก สคริปต์ที่คุณไม่สนใจ ดังนั้นแอปพลิเคชันจึงสามารถกรองข้อผิดพลาดที่มีลักษณะเช่นนี้ออกได้ อย่างไรก็ตาม สิ่งนี้จะไม่เกิดขึ้นใน Firefox หรือ Safari หรือ IE11 และ Chrome ก็ไม่ทำเช่นนี้สำหรับ try/catch บล็อกที่ล้อมโค้ดที่ละเมิด
หากคุณต้องการได้รับข้อผิดพลาดใน window.onerror
ใน Chrome ที่มีความเที่ยงตรงสมบูรณ์จากสคริปต์ข้ามโดเมน ทรัพยากรเหล่านั้นจะต้องมีส่วนหัวข้ามต้นทางที่เหมาะสม ดูhttps://mikewest.org/2013/08/debugging-runtime-errors-with-window-onerrorสำหรับข้อมูลเพิ่มเติม
Chrome เป็นเบราว์เซอร์เดียวที่จะกำจัดข้อผิดพลาดที่มาจากแหล่งอื่น โปรดระมัดระวังในการกรองสิ่งเหล่านี้ออก หรือตั้งค่าส่วนหัวที่เหมาะสม
ส่วนขยายของ Chrome
ใน Chrome เวอร์ชันเก่า ส่วนขยายของ Chrome ที่ติดตั้งในเครื่องของผู้ใช้อาจทำให้เกิดข้อผิดพลาดที่ได้รับการรายงานไปยัง window.onerror ปัญหานี้ได้รับการแก้ไขแล้วใน Chrome เวอร์ชันใหม่กว่า ดูส่วนส่วนขยาย Chrome เฉพาะด้านล่าง
window.addEventListener("error")
API ทำงานเหมือนกับ window.onerror API ดูhttp://www.w3.org/html/wg/drafts/html/master/webappapis.html#runtime-script-errorsสำหรับข้อมูลเพิ่มเติมเกี่ยวกับวิธีการนี้
การตรวจจับข้อผิดพลาดผ่าน window.onerror ไม่ได้ป้องกันข้อผิดพลาดนั้นไม่ให้ปรากฏในคอนโซล DevTools ด้วย นี่น่าจะเป็นพฤติกรรมที่เหมาะสมสำหรับการพัฒนาเนื่องจากนักพัฒนาสามารถเห็นข้อผิดพลาดได้ง่าย หากคุณไม่ต้องการให้ข้อผิดพลาดเหล่านี้แสดงในการใช้งานจริงแก่ผู้ใช้ คุณสามารถเรียก e.preventDefault()
ได้หากใช้วิธี window.addEventListener
window.onerror เป็นเครื่องมือที่ดีที่สุดในการตรวจจับและรายงานข้อผิดพลาด JS ขอแนะนำให้รายงานเฉพาะข้อผิดพลาด JS ที่มีออบเจ็กต์ข้อผิดพลาดที่ถูกต้องและการติดตามสแต็กกลับไปยังเซิร์ฟเวอร์ มิฉะนั้นข้อผิดพลาดอาจตรวจสอบได้ยาก หรือคุณอาจได้รับสแปมจำนวนมากจากส่วนขยายของ Chrome หรือสคริปต์ข้ามโดเมน
จากหัวข้อข้างต้น ขออภัยที่ไม่สามารถใช้ window.onerror
ในเบราว์เซอร์ทั้งหมดเพื่อรวบรวมข้อมูลข้อผิดพลาดทั้งหมดได้ สำหรับการตรวจจับข้อยกเว้นในเครื่อง บล็อก try/catch เป็นตัวเลือกที่ชัดเจน นอกจากนี้ยังสามารถรวมไฟล์ JavaScript ทั้งหมดไว้ในบล็อก try/catch เพื่อบันทึกข้อมูลข้อผิดพลาดที่ไม่สามารถตรวจจับได้ด้วย window.onerror วิธีนี้ช่วยปรับปรุงสถานการณ์สำหรับเบราว์เซอร์ที่ไม่รองรับ window.onerror แต่ก็มีข้อเสียอยู่บ้างเช่นกัน
บล็อก try/catch จะไม่จับข้อผิดพลาดทั้งหมดในโปรแกรม เช่น ข้อผิดพลาดที่ส่งมาจากบล็อกอะซิงก์ของโค้ดผ่าน window.setTimeout
สามารถใช้ Try/catch กับ Protected Entry Points เพื่อช่วยเติมเต็มช่องว่าง
try/catch บล็อกที่รวมแอปพลิเคชันทั้งหมดไม่เพียงพอที่จะตรวจจับข้อผิดพลาดทั้งหมด
V8 เวอร์ชันเก่า (และอาจเป็นเอ็นจิ้น JS อื่นๆ) ฟังก์ชันที่มีบล็อก try/catch จะไม่ได้รับการปรับให้เหมาะสมโดยคอมไพเลอร์ (http://www.html5rocks.com/en/tutorials/speed/v8/) Chrome แก้ไขสิ่งนี้ใน TurboFan (https://codereview.chromium.org/1996373002)
"จุดเริ่มต้น" ใน JavaScript คือ API ของเบราว์เซอร์ที่สามารถเริ่มเรียกใช้โค้ดของคุณได้ ตัวอย่างได้แก่ setTimeout
, setInterval
, event Listeners, XHR, เว็บซ็อกเก็ต หรือสัญญา ข้อผิดพลาดที่ถูกส่งออกมาจากจุดเข้าใช้งานเหล่านี้จะถูกจับโดย window.onerror แต่ในเบราว์เซอร์ที่ไม่รองรับอ็อบเจ็กต์ Error แบบเต็มใน window.onerror จำเป็นต้องใช้กลไกทางเลือกเพื่อตรวจจับข้อผิดพลาดเหล่านี้ เนื่องจากวิธี try/catch กล่าวถึง ข้างบนก็ไม่จับเช่นกัน
โชคดีที่ JavaScript อนุญาตให้รวมจุดเข้าเหล่านี้เพื่อให้สามารถแทรกบล็อก try/catch ก่อนที่จะเรียกใช้ฟังก์ชันเพื่อตรวจจับข้อผิดพลาดที่เกิดจากโค้ด
แต่ละจุดเริ่มต้นจะต้องมีรหัสที่แตกต่างกันเล็กน้อยเพื่อปกป้องจุดเริ่มต้น แต่สาระสำคัญของวิธีการคือ:
ฟังก์ชั่น ProtectEntryPoint (fn) { ฟังก์ชั่น return protectedFn() {ลอง { return fn();} catch (e) { // จัดการข้อผิดพลาด} }`oldSetTimeout = window.setTimeout; window.setTimeout = ฟังก์ชัน protectedSetTimeout (fn, เวลา) { return _oldSetTimeout.call (หน้าต่าง, ProtectEntryPoint (fn), เวลา);};
น่าเศร้าที่ข้อผิดพลาดที่เกิดขึ้นใน Promises มักถูกละเลยและไม่ได้รับการรายงานเป็นเรื่องง่าย ข้อผิดพลาดที่เกิดขึ้นใน Promise แต่ไม่ได้รับการจัดการโดยการแนบตัวจัดการการปฏิเสธจะไม่ถูกรายงานที่อื่น - ข้อผิดพลาดเหล่านี้จะ ไม่ ได้รับการรายงานไปที่ window.onerror
แม้ว่า Promise จะแนบตัวจัดการการปฏิเสธมาด้วย แต่โค้ดนั้นจะต้องรายงานข้อผิดพลาดเหล่านั้นด้วยตนเองเพื่อให้ระบบบันทึกข้อผิดพลาดดังกล่าว ดูhttp://www.html5rocks.com/en/tutorials/es6/promises/#toc-error-handlingสำหรับข้อมูลเพิ่มเติม ตัวอย่างเช่น:
window.onerror = ฟังก์ชั่น (...) { // สิ่งนี้จะไม่ถูกเรียกใช้โดยรหัส Promise.};var p = new Promise(...);p.then(function() { Throw new Error("ข้อผิดพลาดนี้จะไม่ได้รับการจัดการที่ใดก็ได้");});var p2 = new Promise(...);p2.then(function() { Throw new Error("ข้อผิดพลาดนี้จะถูกจัดการในห่วงโซ่");}).catch(function(error) { // แสดงข้อความแสดงข้อผิดพลาดแก่ผู้ใช้ // รหัสนี้ควรรายงานข้อผิดพลาดด้วยตนเองเพื่อเข้าสู่ระบบเซิร์ฟเวอร์ ถ้ามี});
วิธีหนึ่งในการรวบรวมข้อมูลเพิ่มเติมคือการใช้ Protected Entry Points เพื่อรวมการเรียกใช้เมธอด Promise ด้วยการลอง/จับเพื่อรายงานข้อผิดพลาด นี่อาจมีลักษณะดังนี้:
var _oldPromiseThen = Promise.prototype.then; Promise.prototype.then = ฟังก์ชั่น protectedThen (โทรกลับ, errorHandler) {return _oldPromiseThen.call (นี้, ProtectEntryPoint (โทรกลับ), ProtectEntryPoint (errorHandler)); -
น่าเศร้าที่ข้อผิดพลาดจาก Promises ไม่ได้รับการจัดการตามค่าเริ่มต้น
การใช้งานตามสัญญา เช่น Q, Bluebird และการปิดการจัดการข้อผิดพลาดในรูปแบบต่างๆ ซึ่งดีกว่าการจัดการข้อผิดพลาดในการใช้งานเบราว์เซอร์ของ Promises
ใน Q คุณสามารถ "ยุติ" Promise chain ได้โดยการเรียก .done()
ซึ่งจะทำให้แน่ใจได้ว่าหากข้อผิดพลาดไม่ได้รับการจัดการใน chain ก็จะถูกเขียนใหม่และรายงาน ดูhttps://github.com/kriskowal/q#handling-errors
ใน Bluebird การปฏิเสธที่ไม่สามารถจัดการได้จะถูกบันทึกและรายงานทันที ดูhttp://bluebirdjs.com/docs/features.html#surfacing-unhandled-errors
ในการใช้งาน goog.Promise ของการปิด การปฏิเสธที่ไม่ได้จัดการจะถูกบันทึกและรายงานหากไม่มีสายโซ่ใน Promise จัดการการปฏิเสธภายในช่วงเวลาที่กำหนดค่าได้ (เพื่ออนุญาตให้ใช้โค้ดในภายหลังในโปรแกรมเพื่อเพิ่มตัวจัดการการปฏิเสธ)
ส่วนการติดตามสแต็กอะซิงก์ด้านบนอธิบายว่าเบราว์เซอร์ไม่เก็บข้อมูลสแต็กเมื่อมีฮุคอะซิงก์ เช่น การเรียก Promise.prototype.then
Polyfills ที่สัญญาไว้มีวิธีในการจับจุดติดตามสแต็ก async ซึ่งสามารถทำให้การวินิจฉัยข้อผิดพลาดง่ายขึ้นมาก วิธีการนี้มีราคาแพง แต่อาจมีประโยชน์มากในการรวบรวมข้อมูลการดีบักเพิ่มเติม
ใน Q ให้เรียก Q.longStackSupport = true;
- ดูhttps://github.com/kriskowal/q#long-stack-traces
ใน Bluebird ให้เรียก Promise.longStackTraces()
ที่ใดที่หนึ่งในแอปพลิเคชัน ดูhttp://bluebirdjs.com/docs/features.html#long-stack-traces
ในการปิด ให้ตั้งค่า goog.Promise.LONG_STACK_TRACES
เป็นจริง
Chrome 49 เพิ่มการรองรับเหตุการณ์ที่ถูกส่งไปเมื่อสัญญาถูกปฏิเสธ ซึ่งช่วยให้แอปพลิเคชันสามารถเชื่อมต่อกับข้อผิดพลาดของ Promise เพื่อให้แน่ใจว่าจะได้รับรายงานจากส่วนกลางพร้อมกับข้อผิดพลาดที่เหลือ
window.addEventListener('unhandledrejection', event => { // event.reason มีเหตุผลในการปฏิเสธ เมื่อเกิดข้อผิดพลาด นี่คือวัตถุ Error});
ดู https://googlechrome.github.io/samples/promise-rejection-events/ และ https://www.chromestatus.com/feature/4805872211460096 สำหรับข้อมูลเพิ่มเติม
สิ่งนี้ไม่รองรับในเบราว์เซอร์อื่น
คนทำงานเว็บ รวมถึงคนทำงานเฉพาะ คนทำงานที่ใช้ร่วมกัน และคนทำงานบริการ กำลังได้รับความนิยมมากขึ้นในแอปพลิเคชันในปัจจุบัน เนื่องจากผู้ปฏิบัติงานเหล่านี้ทั้งหมดเป็นสคริปต์ที่แยกจากหน้าหลัก พวกเขาแต่ละคนจึงจำเป็นต้องมีรหัสการจัดการข้อผิดพลาดของตนเอง ขอแนะนำให้แต่ละสคริปต์ของผู้ปฏิบัติงานติดตั้งการจัดการข้อผิดพลาดและรหัสการรายงานของตนเองเพื่อการจัดการข้อผิดพลาดที่มีประสิทธิภาพสูงสุดจากผู้ปฏิบัติงาน
พนักงานเว็บโดยเฉพาะจะดำเนินการในบริบทการดำเนินการที่แตกต่างจากหน้าหลัก ดังนั้นกลไกข้างต้นจึงไม่ตรวจพบข้อผิดพลาดจากผู้ปฏิบัติงาน จำเป็นต้องดำเนินการขั้นตอนเพิ่มเติมเพื่อตรวจจับข้อผิดพลาดจากผู้ปฏิบัติงานบนเพจ
เมื่อสร้างผู้ปฏิบัติงานแล้ว คุณสมบัติ onerror สามารถตั้งค่าให้กับผู้ปฏิบัติงานใหม่ได้:
var worker = new Worker('worker.js');worker.onerror = function(errorEvent) { ... };
ซึ่งกำหนดไว้ในhttps://html.spec.whatwg.org/multipage/workers.html#handler-abstractworker-onerror ฟังก์ชัน onerror
ของผู้ปฏิบัติงานมีลายเซ็นที่แตกต่างจาก window.onerror
ที่กล่าวถึงข้างต้น แทนที่จะยอมรับ 5 อาร์กิวเมนต์ worker.onerror
รับอาร์กิวเมนต์เดียว: อ็อบเจ็กต์ ErrorEvent
API สำหรับวัตถุนี้สามารถพบได้ที่https://developer.mozilla.org/en-US/docs/Web/API/ErrorEvent ประกอบด้วยข้อความ ชื่อไฟล์ บรรทัด และคอลัมน์ แต่ปัจจุบันไม่มีเบราว์เซอร์ที่เสถียรซึ่งมีออบเจ็กต์ "ข้อผิดพลาด" ที่มีการติดตามสแต็ก (errorEvent.error เป็น null) เนื่องจาก API นี้ดำเนินการในขอบเขตของเพจหลัก จึงจะเป็นประโยชน์สำหรับการใช้กลไกการรายงานเดียวกันกับเพจหลัก น่าเสียดาย เนื่องจากไม่มีการติดตามสแต็ก API นี้จึงมีการใช้งานอย่างจำกัด
ภายใน JS ที่ดำเนินการโดยผู้ปฏิบัติงาน คุณยังสามารถกำหนด onerror API ที่ตามหลัง window.onerror API ปกติ: https://html.spec.whatwg.org/multipage/webappapis.html#onerroreventhandler ในรหัสพนักงาน:
self.onerror = function(ข้อความ, ชื่อไฟล์, บรรทัด, คอลัมน์, ข้อผิดพลาด) { ... };
การอภิปรายเกี่ยวกับ API นี้ส่วนใหญ่เป็นไปตามการสนทนาด้านบนสำหรับ window.onerror อย่างไรก็ตาม มีประเด็นที่น่าสังเกตอยู่ 2 ประการ คือ
Firefox และ Safari ไม่รายงานวัตถุ "ข้อผิดพลาด" เป็นอาร์กิวเมนต์ที่ 5 ของฟังก์ชัน ดังนั้นเบราว์เซอร์เหล่านี้จึงไม่ได้รับการติดตามสแต็กจากผู้ปฏิบัติงาน (Chrome, MS Edge และ IE11 จะได้รับการติดตามสแต็ก) จุดเริ่มต้นที่ได้รับการป้องกันสำหรับฟังก์ชัน onmessage
ภายในผู้ปฏิบัติงานสามารถใช้เพื่อรวบรวมข้อมูลการติดตามสแต็กสำหรับเบราว์เซอร์เหล่านี้
เนื่องจากโค้ดนี้ทำงานภายในผู้ปฏิบัติงาน โค้ดจะต้องเลือกวิธีรายงานข้อผิดพลาดกลับไปยังเซิร์ฟเวอร์: ต้องใช้ postMessage
เพื่อสื่อสารข้อผิดพลาดกลับไปยังเพจหลัก หรือติดตั้งกลไกการรายงานข้อผิดพลาด XHR (อธิบายเพิ่มเติมด้านล่าง) ใน คนงานเอง
ใน Firefox, Safari และ IE11 (แต่ไม่ใช่ใน Chrome) ฟังก์ชัน window.onerror
ของเพจหลักจะถูกเรียกหลังจาก onerror ของผู้ปฏิบัติงานเอง และตัวฟังเหตุการณ์ onerror ที่ตั้งค่าโดยเพจนั้นถูกเรียกแล้ว อย่างไรก็ตาม window.onerror นี้จะไม่มีออบเจ็กต์ข้อผิดพลาด ดังนั้นจึงไม่มีการติดตามสแต็กด้วย เบราว์เซอร์เหล่านี้จะต้องดูแลไม่รายงานข้อผิดพลาดจากผู้ปฏิบัติงานหลายครั้ง
Chrome และ Firefox รองรับ SharedWorker API สำหรับการแบ่งปันพนักงานระหว่างหลายเพจ เนื่องจากมีการแบ่งปันผู้ปฏิบัติงาน จึงไม่ได้แนบไปกับเพจหลักเพียงเพจเดียว สิ่งนี้นำไปสู่ความแตกต่างบางประการในการจัดการกับข้อผิดพลาด แม้ว่า SharedWorker ส่วนใหญ่จะติดตามข้อมูลเดียวกันกับผู้ปฏิบัติงานบนเว็บโดยเฉพาะ
ใน Chrome เมื่อมีข้อผิดพลาดใน SharedWorker ระบบจะเรียกเฉพาะข้อผิดพลาดของผู้ปฏิบัติงานที่จัดการภายในโค้ดของผู้ปฏิบัติงานเท่านั้น (เช่น หากพวกเขาตั้งค่า self.onerror
) window.onerror
ของหน้าหลักจะไม่ถูกเรียก และ Chrome ไม่สนับสนุน AbstractWorker.onerror
ที่สืบทอดมา ซึ่งสามารถเรียกได้ในหน้าหลักตามที่กำหนดไว้ในข้อมูลจำเพาะ
ใน Firefox ลักษณะการทำงานนี้จะแตกต่างออกไป ข้อผิดพลาดในผู้ปฏิบัติงานที่ใช้ร่วมกันจะทำให้มีการเรียก window.onerror ของเพจหลัก แต่วัตถุข้อผิดพลาดจะเป็นโมฆะ นอกจากนี้ Firefox ยังสนับสนุนคุณสมบัติ AbstractWorker.onerror
ดังนั้นเพจหลักจึงสามารถแนบตัวจัดการข้อผิดพลาดของตนเองกับผู้ปฏิบัติงานได้ อย่างไรก็ตาม เมื่อเรียกใช้ตัวจัดการข้อผิดพลาดนี้ ออบเจ็กต์ข้อผิดพลาดจะเป็นโมฆะ ดังนั้นจะไม่มีการติดตามสแต็ก ดังนั้นจึงมีการใช้งานที่จำกัด
การจัดการข้อผิดพลาดสำหรับพนักงานที่ใช้ร่วมกันจะแตกต่างกันไปตามเบราว์เซอร์
Service Workers เป็นข้อมูลจำเพาะใหม่ล่าสุดที่ปัจจุบันมีเฉพาะใน Chrome และ Firefox เวอร์ชันล่าสุดเท่านั้น ผู้ปฏิบัติงานเหล่านี้ปฏิบัติตามการสนทนาเดียวกันกับผู้ปฏิบัติงานบนเว็บโดยเฉพาะ
พนักงานบริการได้รับการติดตั้งโดยการเรียกฟังก์ชัน navigator.serviceWorker.register
ฟังก์ชันนี้ส่งคืน Promise ซึ่งจะถูกปฏิเสธหากมีข้อผิดพลาดในการติดตั้งโปรแกรมทำงานของบริการ เช่น เกิดข้อผิดพลาดระหว่างการเริ่มต้น ข้อผิดพลาดนี้จะมีเฉพาะข้อความสตริงเท่านั้นและไม่มีอะไรอื่นอีก นอกจากนี้ เนื่องจาก Promises ไม่รายงานข้อผิดพลาดไปยังตัวจัดการ window.onerror
ตัวแอปพลิเคชันเองจึงต้องเพิ่ม catch block ให้กับ Promise เพื่อตรวจจับข้อผิดพลาด
navigator.serviceWorker.register('บริการพนักงานติดตั้ง-error.js').catch(ฟังก์ชั่น(ข้อผิดพลาด) { // ประเภทของข้อผิดพลาดของสตริง});
เช่นเดียวกับพนักงานคนอื่นๆ พนักงานบริการสามารถตั้งค่าฟังก์ชัน self.onerror
ภายในพนักงานบริการเพื่อตรวจจับข้อผิดพลาด ข้อผิดพลาดในการติดตั้งใน Service Worker จะถูกรายงานไปยังฟังก์ชัน onerror แต่น่าเสียดายที่ไม่มีออบเจ็กต์ข้อผิดพลาดหรือการติดตามสแต็ก
API ของพนักงานบริการมีคุณสมบัติ onerror ที่สืบทอดมาจากอินเทอร์เฟซ AbstractWorker แต่ Chrome ไม่ได้ทำอะไรเลย