Computer >> คอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Ruby

การช่วยเหลือข้อยกเว้นใน Ruby

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

เมื่อช่วยเหลือข้อยกเว้นใน Ruby คุณสามารถระบุคลาสข้อผิดพลาดเฉพาะที่ควรได้รับการช่วยเหลือ

begin
  raise 'This exception will be rescued!'
rescue StandardError => e
  puts "Rescued: #{e.inspect}"
end

หมายเหตุ :เมื่อใช้ raise โดยไม่ระบุคลาสข้อยกเว้น Ruby จะใช้ค่าเริ่มต้นเป็น RuntimeError .

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

begin
  raise 'This exception will be rescued!'
rescue StandardError, AnotherError => e
  puts "Rescued: #{e.inspect}"
end

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

begin
  raise 'This exception will be rescued!'
rescue StandardError => e
  puts "Rescued: #{e.inspect}"
rescue AnotherError => e
  puts "Rescued, but with a different block: #{e.inspect}"
end

ลำดับชั้นข้อยกเว้น

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

แม้ว่าไลบรารี่สามารถกำหนดคลาสย่อยข้อยกเว้นของตนเองได้ แต่รายการของคลาสย่อยข้อยกเว้นในตัวบน Ruby 2.5 จะมีลักษณะดังนี้:

- NoMemoryError
- ScriptError
    - LoadError
    - NotImplementedError
    - SyntaxError
- SecurityError
- SignalException
    - Interrupt
- StandardError (default for `rescue`)
    - ArgumentError
        - UncaughtThrowError
    - EncodingError
    - FiberError
    - IOError
        - EOFError
    - IndexError
        - KeyError
        - StopIteration
    - LocalJumpError
    - NameError
        - NoMethodError
    - RangeError
        - FloatDomainError
    - RegexpError
    - RuntimeError (default for `raise`)
    - SystemCallError
        - Errno::*
    - ThreadError
    - TypeError
    - ZeroDivisionError
- SystemExit
- SystemStackError
- fatal (impossible to rescue)

เมื่อละเว้นคลาสข้อยกเว้นใน rescue บล็อก StandardError จะถือว่า เพราะ ArgumentError และ NoMethodError เป็นคลาสย่อยของ StandardError สิ่งเหล่านี้จะได้รับการช่วยเหลือเมื่อเกิดขึ้นในบล็อก

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

File.readของ Ruby เมธอดจะทำให้เกิดข้อยกเว้นหากไม่สามารถอ่านไฟล์ได้ ที่อาจเกิดขึ้นได้จากหลายสาเหตุ เช่น ไฟล์ไม่มีอยู่หรือโปรแกรมไม่มีสิทธิ์ในการอ่านที่ถูกต้อง

เนื่องจากปัญหาเหล่านี้ขึ้นอยู่กับแพลตฟอร์ม Ruby จึงสามารถยกข้อยกเว้นต่างๆ ขึ้นได้ขึ้นอยู่กับชนิดของระบบปฏิบัติการที่รันอยู่บนเครื่อง สำหรับข้อผิดพลาดระดับต่ำเช่นนี้ Ruby ใช้รายการ Errno::* ที่แตกต่างกัน -ข้อยกเว้นสำหรับแต่ละแพลตฟอร์ม

Errno::* . ทั้งหมดนี้ ข้อยกเว้นคือคลาสย่อยของ SystemCallError . แม้ว่าจะเป็นเฉพาะแพลตฟอร์ม แต่ก็ยังใช้ใน rescue . ได้ บล็อกโดยการช่วยเหลือจาก SystemCallError .

begin
  File.read("does/not/exist")
rescue SystemCallError => e
  puts "Rescued: #{e.inspect}"
end

ข้อยกเว้นการกลืน

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

image = nil
 
begin
  File.read(image.filename)
rescue
  puts "File can't be read!"
end

ในตัวอย่างนี้ image ตัวแปร nil ดังนั้นจึงทำให้เกิด NoMethodError เมื่อเราพยายามเรียก #filename กับมัน (NoMethodError: undefined method `filename' for nil:NilClass ). เพราะทุก StandardError คลาสย่อยได้รับการช่วยเหลือจาก (รวมถึง NoMethodError ) ระบบจะกลืนข้อยกเว้นและพิมพ์ข้อความ "ไม่สามารถอ่านไฟล์ได้!" สิ่งนี้ซ่อนข้อบกพร่องที่เป็นไปได้ในโค้ด

หมายเหตุ :แม้ว่าจะเป็นไปได้โดยใช้ Exception ซูเปอร์คลาสใน rescue บล็อกนี้ท้อแท้มาก

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