แนวทางปฏิบัติที่ดีที่สุดสำหรับการจัดการข้อผิดพลาดของ JavaScript คืออะไร?


137

ฉันกำลังมองหาการเริ่มต้นทำ JavaScript หลักฐานข้อผิดพลาดของฉันอีกเล็กน้อยและฉันพบความอุดมสมบูรณ์ของเอกสารเกี่ยวกับการใช้try, catch, finallyและthrowแต่ฉันไม่ได้หาตันของคำแนะนำจากผู้เชี่ยวชาญเกี่ยวกับเวลาและสถานที่ที่จะโยนความผิดพลาด

  • รหัสทุกชิ้นควรห่อด้วย try / catch หรือไม่?
  • มีคำแนะนำเพิ่มเติมเกี่ยวกับข้อผิดพลาดในจุดใดที่ควรจับได้หรือไม่?
  • มีข้อเสียในการเพิ่มข้อผิดพลาดแทนที่จะให้รหัสล้มเหลวในการใช้งานจริงหรือไม่?
  • สิ่งนี้ได้รับการสัมผัสบน SO จนถึงการใช้งาน แต่มีข้อผิดพลาด JS ในการบันทึกเซิร์ฟเวอร์เป็นกลยุทธ์ที่มีประสิทธิภาพหรือไม่?
  • มีอะไรอีกบ้างที่ฉันควรทราบเกี่ยวกับข้อผิดพลาดในการดักจับในแอปพลิเคชันของฉัน

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

ขอบคุณสำหรับคำแนะนำที่คุณสามารถให้ได้!


ขึ้นอยู่กับว่าคุณล้มเหลวอย่างน่าประทับใจเพียงใดหากมีบางอย่างผิดพลาดและปริมาณของข้อความแสดงข้อผิดพลาดที่เป็นไปได้ คุณไม่ต้องการล้มเหลวเพราะไดเรกทอรีบันทึกข้อผิดพลาดของคุณเต็มแล้วใช่หรือไม่? - คุณดูที่นี่หรือไม่? stackoverflow.com/search?q=error+logging+javascript
mplungjan

@mplungjan - ฉันสแกนหาคำตอบที่นั่น แต่ดูเหมือนจะไม่เป็นที่ยอมรับมากนักและการค้นหาแนวทางปฏิบัติที่ดีที่สุดในการจัดการข้อผิดพลาด / ข้อยกเว้นของ Javascript ก็ไม่ได้ผลอะไรเลยดังนั้นฉันคิดว่ามันจะเป็นประโยชน์ที่จะพยายามเรียกร้องความคิดที่ย่อบางอย่างทั้งสำหรับฉัน ความเข้าใจของตัวเองและผู้ค้นหาในอนาคต บางทีนี่อาจเป็นหัวข้อที่ไม่สามารถกำหนดแนวทางปฏิบัติที่ดีที่สุดได้ แต่แต่ละสถานการณ์มีความแตกต่างกันอย่างมาก?
Joshua Cody

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

1
นี่เป็นคำถามที่ดี Josh, +1 มีคำแนะนำเกี่ยวกับวากยสัมพันธ์มากมาย แต่อย่างที่คุณบอกว่าเป็นส่วนที่ง่าย ในคำตอบของคำถามนี้ ( stackoverflow.com/questions/2825427/… ) ซึ่งอธิบายว่าข้อยกเว้นไม่ได้ใช้กันทั่วไปใน JS และให้เหตุผล
whitneyland

คำตอบ:


63

ชุดสไลด์ที่น่าสนใจอย่างมากใน Enterprise JavaScript Error Handling สามารถพบได้ที่http://www.devhands.com/2008/10/javascript-error-handling-and-general-best-practices/

สรุปโดยย่อ:

  1. สมมติว่ารหัสของคุณล้มเหลว
  2. บันทึกข้อผิดพลาดไปยังเซิร์ฟเวอร์
  3. คุณไม่ใช่เบราว์เซอร์ที่จัดการกับข้อผิดพลาด
  4. ระบุตำแหน่งที่อาจเกิดข้อผิดพลาด
  5. โยนข้อผิดพลาดของคุณเอง
  6. แยกแยะข้อผิดพลาดร้ายแรงและไม่ร้ายแรง
  7. จัดเตรียมโหมดดีบัก

สไลด์มีรายละเอียดมากขึ้นและส่วนใหญ่อาจให้คำแนะนำแก่คุณได้

UPDATE

การนำเสนอดังกล่าวข้างต้นสามารถพบได้ที่นี่: http://www.slideshare.net/nzakas/enterprise-javascript-error-handling-presentation


24
ลิงก์ devhands เสีย
Ryan Gates

7
สำหรับผู้ที่อ่านสิ่งนี้ในปี 2560 ฉันขอยืนยันว่าคุณจะไม่ได้รับคุณค่าจากสไลด์มากนัก - สรุปนี้ให้ข้อมูล 90% มันยังคงเป็นข้อมูลที่มีค่า ไชโย!
Philippe Hebert

29

Nicholas Zakas แห่ง Yahoo! ชื่อเสียงได้พูดคุยเกี่ยวกับการจัดการข้อผิดพลาดขององค์กร ( สไลด์ ) ที่ Ajax Experience 2008 ซึ่งเขาเสนอสิ่งนี้:

function log(sev,msg) {
    var img = new Image();
    img.src = "log.php?sev=" +
        encodeURIComponent(sev) +
        "&msg=" + encodeURIComponent(msg);
}

// usage
log(1, "Something bad happened.")

// Auto-log uncaught JS errors
window.onerror = function(msg, url, line) {
    log(1, msg);
    return true;
}

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

เมื่อคุณเริ่มบันทึกหน้าต่างการโทรผิดพลาดคุณจะสังเกตเห็นสองสิ่ง:

  1. หากไซต์ของคุณค่อนข้างซับซ้อนคุณจะบันทึกข้อผิดพลาดจำนวนมาก
  2. คุณจะเห็น "window.error ที่ไร้ประโยชน์จำนวนมากใน undefined: 0" ข้อความ

การลดทอร์เรนต์ของรายการบันทึกทำได้ง่ายๆเพียงแค่ทดสอบความรุนแรงและ / หรือหมายเลขสุ่มก่อนที่จะเข้าสู่เซิร์ฟเวอร์:

function log(sev,msg) {
    if (Math.random() > 0.1) return; // only log some errors

    var img = new Image();
    img.src = "log.php?sev=" +
        encodeURIComponent(sev) +
        "&msg=" + encodeURIComponent(msg);
}

การจัดการข้อผิดพลาด window.error ใน undefined: 0 "ที่ไร้ประโยชน์นั้นขึ้นอยู่กับสถาปัตยกรรมไซต์ของคุณ แต่สามารถลองระบุการเรียก Ajax ทั้งหมดและทิ้งข้อยกเว้นเมื่อมีบางอย่างล้มเหลว (อาจส่งคืนการติดตามสแต็กโดยใช้stacktrace.js )


67
ฉันรู้ว่านี่เป็นคำถามเก่า แต่การแนะนำให้สุ่มเพิกเฉยต่อข้อผิดพลาดบางอย่างเป็นหนึ่งในแนวคิดที่แย่ที่สุดที่ฉันเคยได้ยินมา
jbabey

26
@jbabey: สำหรับไซต์เล็ก ๆ คุณพูดถูก แต่ถ้าคุณใช้งานไซต์ขนาดใหญ่ที่มีผู้ใช้ 100,000 คนหรือหลายล้านคนคุณไม่จำเป็นต้องท่วมเซิร์ฟเวอร์ (หรืออินเทอร์เน็ต) ด้วยคำขอบันทึกซ้ำซ้อน ในระบบที่ใหญ่พอข้อผิดพลาดจริงทุกอย่างจะเกิดขึ้นวันละหลายหมื่นครั้งดังนั้นการ จำกัด รูปแบบนี้จึงใช้ได้ดี แนวคิดดังกล่าวถูกนำไปใช้จริงที่ Facebook
Jens Roland

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

2
@NickBull ฉันย้อนกระบวนการสร้างโมดูล JavaScript ของ Facebooks ในปี 2554-2555 นั่นคือสิ่งที่ฉันพบ
Jens Roland

1
@NickBull เพิ่งตรวจสอบไฟล์เก่าของฉันยังมีไฟล์เหล่านี้อยู่ ฉันพบเคล็ดลับนี้ในโมดูล bootloader ของ Facebook: if (global.logJSError) if (Math.random() < .01) logJSError('bootloader', {(ยอมรับว่ารหัสไม่ได้ จำกัด ข้อผิดพลาดทั้งหมดมีเพียงข้อผิดพลาดการหมดเวลาที่เฉพาะเจาะจงเท่านั้น)
Jens Roland

7

IHMO คุณควรใช้การจัดการข้อผิดพลาดในจาวาสคริปต์เช่นเดียวกับที่คุณทำในภาษาอื่น ๆ (AFAIK: Python, Java)

เพื่อให้อ่านง่ายขึ้น (และอาจมีประสิทธิภาพที่ดีขึ้นแม้ว่าฉันจะไม่แน่ใจว่ามันมีผลกระทบอย่างมากก็ตาม) คุณควรใช้บล็อก try / catch เป็นส่วนใหญ่ในกรณีต่อไปนี้:

  • ส่วนหนึ่งของรหัสที่คุณต้องการที่จะห่อเป็นสำคัญส่วนหนึ่งของขั้นตอนวิธีการทั้งหมด หากล้มเหลวอาจ:

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

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

ในที่สุดผู้เชี่ยวชาญด้านจาวาสคริปต์อาจมีองค์ประกอบอื่น ๆ ให้

2 เซ็นต์ของฉันไปที่กล่อง

ความนับถือ,

แม็กซ์


1
"ส่วนของโค้ดที่คุณต้องการรวมเป็นส่วนสำคัญของอัลกอริทึมทั้งหมด" - อาจขึ้นอยู่กับว่าคุณต้องการจัดการกับความล้มเหลวอย่างไร หากคุณรู้ว่าไม่มีวิธีดำเนินการต่อกับอัลกอริทึมเมื่อเกิดความล้มเหลวอาจเป็นการดีกว่าที่จะรวมสิ่งทั้งหมดด้วยการลอง / จับเพราะถ้าการลอง / จับของคุณถูก (เช่น) ฝังอยู่ในลูปที่ซ้อนกันมันจะเป็นการเพิ่มประสิทธิภาพ . ในทางกลับกันหากคุณสามารถดำเนินการบางอย่างในข้อยกเว้นและดำเนินการต่อด้วยอัลกอริทึมคุณจะต้องมีการตั้งค่าการลอง / จับที่ละเอียดยิ่งขึ้น
nnnnnn

5

นอกเหนือจากคำตอบอื่น ๆ : สิ่งสำคัญอย่างหนึ่งคือการใช้ข้อมูลบริบทที่มีอยู่ในวัตถุข้อผิดพลาดของ JavaScript และในwindow.onerrorพารามิเตอร์ฟังก์ชัน

สิ่งต่างๆเช่น stacktrace (errorObject.stack) ชื่อไฟล์หมายเลขบรรทัดและหมายเลขคอลัมน์ โปรดทราบว่าแต่ละเบราว์เซอร์มีความแตกต่างกัน ... ดังนั้นพยายามอย่างเต็มที่เพื่อให้ได้ข้อผิดพลาดที่ดี

มีแม้กระทั่งอาจมีปัญหากับวัตถุคอนโซลตัวเอง ฉันใช้ฟังก์ชัน window.onerror ที่กำหนดเองซึ่งได้รับแรงบันดาลใจจากฟังก์ชันนี้และฟังก์ชันพิเศษเพื่อติดตามวัตถุข้อผิดพลาดมาตรฐานใด ๆ ที่ได้รับแรงบันดาลใจจากรหัสนี้

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

นอกจากนี้ยังใช้หลีกเลี่ยงการใช้throw 'My message'ใช้throw new Error('My message')คุณยังสามารถมีข้อผิดพลาดที่กำหนดเองอ่านบทความนี้

เพิ่มบริบทบางอย่างให้กับข้อผิดพลาดเสมอ (เวอร์ชัน, รหัสของวัตถุ, ข้อความที่กำหนดเอง, ... ) และตรวจสอบให้แน่ใจว่าคุณได้แยกความแตกต่างระหว่างข้อผิดพลาดภายนอก (ข้อมูลภายนอกหรือสถานการณ์บางอย่างทำให้ระบบของคุณล้มเหลว) และข้อผิดพลาดภายใน / การยืนยัน (ระบบของคุณเองทำงานผิดพลาด) อ่านเกี่ยวกับ ' ออกแบบตามสัญญา '

นี่คือคู่มือ

ลองนึกถึงการใช้การจัดการข้อผิดพลาดทั่วไปเช่นการสกัดกั้น libs และเฟรมเวิร์กของคุณ:

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.