บทความนี้แสดงแนวทางการจัดการข้อผิดพลาดบางส่วนเมื่อทํางานกับ Fetch API Fetch API ช่วยให้คุณส่งคําขอไปยังทรัพยากรเครือข่ายระยะไกลได้ เมื่อคุณเรียกใช้เครือข่ายจากระยะไกล หน้าเว็บอาจเกิดข้อผิดพลาดเกี่ยวกับเครือข่ายได้หลายประการ
ส่วนต่อไปนี้จะอธิบายข้อผิดพลาดที่อาจเกิดขึ้นและอธิบายวิธีเขียนโค้ดที่มอบฟังก์ชันการทำงานในระดับที่เหมาะสมซึ่งทนต่อข้อผิดพลาดและสภาพเครือข่ายที่ไม่คาดคิด โค้ดที่ยืดหยุ่นช่วยให้ผู้ใช้พึงพอใจและรักษาระดับการบริการมาตรฐานสำหรับเว็บไซต์
คาดการณ์ข้อผิดพลาดที่อาจเกิดขึ้นกับเครือข่าย
ส่วนนี้จะอธิบายสถานการณ์ที่ผู้ใช้สร้างวิดีโอใหม่ชื่อ "My Travels.mp4"
แล้วพยายามอัปโหลดวิดีโอไปยังเว็บไซต์แชร์วิดีโอ
เมื่อใช้การเรียกข้อมูล การพิจารณาเส้นทางที่สมบูรณ์ซึ่งผู้ใช้อัปโหลดวิดีโอสำเร็จนั้นง่ายมาก อย่างไรก็ตาม ยังมีเส้นทางอื่นๆ ที่อาจไม่ราบรื่นนัก แต่นักพัฒนาเว็บต้องวางแผนไว้ เส้นทาง (ที่ไม่พึงพอใจ) ดังกล่าวอาจเกิดขึ้นจากข้อผิดพลาดของผู้ใช้ สภาพแวดล้อมที่ไม่คาดคิด หรือข้อบกพร่องในเว็บไซต์การแชร์วิดีโอ
ตัวอย่างข้อผิดพลาดของผู้ใช้
- ผู้ใช้อัปโหลดไฟล์ภาพ (เช่น JPEG) แทนไฟล์วิดีโอ
- ผู้ใช้เริ่มอัปโหลดไฟล์วิดีโอที่ไม่ถูกต้อง จากนั้นระหว่างการอัปโหลด ผู้ใช้ระบุไฟล์วิดีโอที่ถูกต้องสำหรับการอัปโหลด
- ผู้ใช้คลิก "ยกเลิกการอัปโหลด" โดยไม่ได้ตั้งใจขณะที่วิดีโอกำลังอัปโหลด
ตัวอย่างการเปลี่ยนแปลงด้านสิ่งแวดล้อม
- การเชื่อมต่ออินเทอร์เน็ตออฟไลน์ขณะอัปโหลดวิดีโอ
- เบราว์เซอร์รีสตาร์ทขณะที่อัปโหลดวิดีโอ
- เซิร์ฟเวอร์ของเว็บไซต์แชร์วิดีโอรีสตาร์ทขณะที่อัปโหลดวิดีโอ
ตัวอย่างข้อผิดพลาดเกี่ยวกับเว็บไซต์แชร์วิดีโอ
- เว็บไซต์แชร์วิดีโอไม่สามารถจัดการชื่อไฟล์ที่มีเว้นวรรค ต้องการชื่อ เช่น
"My_Travels.mp4"
หรือ"MyTravels.mp4"
แทน"My Travels.mp4"
- เว็บไซต์การแชร์วิดีโออัปโหลดวิดีโอที่มีขนาดใหญ่เกินขนาดไฟล์สูงสุดที่ยอมรับไม่ได้
- เว็บไซต์การแชร์วิดีโอไม่รองรับตัวแปลงรหัสวิดีโอในวิดีโอที่อัปโหลด
ตัวอย่างเหล่านี้อาจเกิดขึ้นได้ในชีวิตจริง คุณอาจเคยเห็นตัวอย่างดังกล่าวมาก่อน เรามาเลือกตัวอย่าง 1 รายการจากแต่ละหมวดหมู่ก่อนหน้านี้และพูดคุยเกี่ยวกับประเด็นต่อไปนี้
- ลักษณะการทำงานเริ่มต้นจะเป็นอย่างไรหากบริการแชร์วิดีโอจัดการกับตัวอย่างที่ระบุไม่ได้
- ผู้ใช้คาดหวังให้เกิดอะไรขึ้นในตัวอย่างนี้
- เราจะปรับปรุงกระบวนการนี้ได้อย่างไร
จัดการข้อผิดพลาดด้วย Fetch API
โปรดทราบว่าตัวอย่างโค้ดต่อไปนี้ใช้ await
ระดับบนสุด (การรองรับเบราว์เซอร์) เนื่องจากฟีเจอร์นี้ช่วยให้โค้ดของคุณเรียบง่ายขึ้น
เมื่อ Fetch API แสดงข้อผิดพลาด
ตัวอย่างนี้ใช้คำสั่งบล็อก try
/catch
เพื่อจับข้อผิดพลาดที่แสดงภายในบล็อก try
เช่น หาก Fetch API ดึงข้อมูลทรัพยากรที่ระบุไม่ได้ ระบบจะแสดงข้อผิดพลาด ภายในบล็อก catch
เช่นนี้ โปรดดูแลให้ผู้ใช้ได้รับประสบการณ์การใช้งานที่มีความหมาย หากระบบแสดงสปินเนอร์ ซึ่งเป็นอินเทอร์เฟซผู้ใช้ทั่วไปที่แสดงถึงขั้นตอนบางอย่างต่อผู้ใช้ คุณจะดําเนินการต่อไปนี้ภายในบล็อก catch
ได้
- นำเครื่องมือหมุนออกจากหน้า
- แสดงข้อความที่เป็นประโยชน์ซึ่งอธิบายสิ่งที่ผิดพลาดและตัวเลือกที่ผู้ใช้ทำได้
- แสดงปุ่ม "ลองอีกครั้ง" ให้ผู้ใช้เห็นโดยอิงตามตัวเลือกที่มี
- เบื้องหลัง ระบบจะส่งรายละเอียดของข้อผิดพลาดไปยังบริการติดตามข้อผิดพลาดหรือแบ็กเอนด์ การดำเนินการนี้จะบันทึกข้อผิดพลาดเพื่อให้สามารถวินิจฉัยในขั้นตอนต่อไป
try {
const response = await fetch('https://website');
} catch (error) {
// TypeError: Failed to fetch
console.log('There was an error', error);
}
ในขั้นตอนต่อมา ขณะที่วินิจฉัยข้อผิดพลาดที่บันทึกไว้ คุณสามารถเขียนกรณีทดสอบเพื่อจับข้อผิดพลาดดังกล่าวก่อนที่ผู้ใช้จะรู้ตัวว่าเกิดข้อผิดพลาด การทดสอบอาจเป็นการทดสอบหน่วย การผสานรวม หรือการยอมรับ ทั้งนี้ขึ้นอยู่กับข้อผิดพลาด
เมื่อรหัสสถานะเครือข่ายแสดงข้อผิดพลาด
ตัวอย่างโค้ดนี้จะส่งคำขอไปยังบริการทดสอบ HTTP ที่ตอบสนองด้วยรหัสสถานะ HTTP 429 Too Many Requests
เสมอ สิ่งที่น่าสนใจคือคำตอบไม่ได้ไปถึงบล็อก catch
สถานะ 404 เป็นหนึ่งในรหัสสถานะอื่นๆ บางรหัสที่ไม่ได้แสดงข้อผิดพลาดเกี่ยวกับเครือข่าย แต่แก้ไขได้ตามปกติ
หากต้องการตรวจสอบว่ารหัสสถานะ HTTP สำเร็จหรือไม่ คุณสามารถใช้ตัวเลือกใดก็ได้ต่อไปนี้
- ใช้พร็อพเพอร์ตี้
Response.ok
เพื่อระบุว่ารหัสสถานะอยู่ในช่วง200
ถึง299
หรือไม่ - ใช้พร็อพเพอร์ตี้
Response.status
เพื่อระบุว่าการตอบกลับสําเร็จหรือไม่ - ใช้ข้อมูลเมตาอื่นๆ เช่น
Response.headers
เพื่อประเมินว่าการตอบกลับสําเร็จหรือไม่
let response;
try {
response = await fetch('https://httpbin.org/status/429');
} catch (error) {
console.log('There was an error', error);
}
// Uses the 'optional chaining' operator
if (response?.ok) {
console.log('Use the response here!');
} else {
console.log(`HTTP Response Code: ${response?.status}`)
}
แนวทางปฏิบัติแนะนำคือให้ทำงานร่วมกับคนในองค์กรและทีมเพื่อทำความเข้าใจรหัสสถานะการตอบกลับ HTTP ที่อาจเกิดขึ้น บางครั้งนักพัฒนาซอฟต์แวร์ฝั่งแบ็กเอนด์ ทีมปฏิบัติการของนักพัฒนาแอป และวิศวกรบริการอาจให้ข้อมูลเชิงลึกที่ไม่เหมือนใครเกี่ยวกับกรณีที่เกิดขึ้นได้ซึ่งคุณอาจคาดไม่ถึง
เมื่อเกิดข้อผิดพลาดในการแยกวิเคราะห์การตอบกลับของเครือข่าย
ตัวอย่างโค้ดนี้แสดงข้อผิดพลาดอีกประเภทหนึ่งที่อาจเกิดขึ้นเมื่อแยกวิเคราะห์ข้อมูลโค้ดตอบกลับ อินเทอร์เฟซ Response
มีวิธีการที่สะดวกในการแยกวิเคราะห์ข้อมูลประเภทต่างๆ เช่น ข้อความหรือ JSON ในโค้ดต่อไปนี้ ระบบจะส่งคําขอเครือข่ายไปยังบริการทดสอบ HTTP ซึ่งจะแสดงสตริง HTML เป็นส่วนเนื้อหาการตอบกลับ อย่างไรก็ตาม ระบบพยายามแยกวิเคราะห์เนื้อหาการตอบกลับเป็น JSON ซึ่งทำให้เกิดข้อผิดพลาด
let json;
try {
const response = await fetch('https://httpbin.org/html');
json = await response.json();
} catch (error) {
if (error instanceof SyntaxError) {
// Unexpected token < in JSON
console.log('There was a SyntaxError', error);
} else {
console.log('There was an error', error);
}
}
if (json) {
console.log('Use the JSON here!', json);
}
คุณต้องเตรียมโค้ดให้รองรับรูปแบบการตอบกลับที่หลากหลาย และตรวจสอบว่าการตอบกลับที่ไม่คาดคิดจะไม่ทำให้หน้าเว็บใช้งานไม่ได้สำหรับผู้ใช้
ลองพิจารณาสถานการณ์ต่อไปนี้ คุณมีทรัพยากรระยะไกลที่แสดงผลการตอบกลับ JSON ที่ถูกต้อง และระบบแยกวิเคราะห์ด้วยเมธอด Response.json()
เรียบร้อยแล้ว บริการอาจหยุดทำงาน เมื่อปิดแล้ว ระบบจะแสดง 500 Internal Server Error
หากไม่ได้ใช้เทคนิคการจัดการข้อผิดพลาดที่เหมาะสมระหว่างการแยกวิเคราะห์ JSON หน้าเว็บอาจใช้งานไม่ได้สำหรับผู้ใช้เนื่องจากระบบจะแสดงข้อผิดพลาดที่ไม่ได้รับการจัดการ
กรณีที่ต้องยกเลิกคําขอเครือข่ายก่อนที่คําขอจะเสร็จสมบูรณ์
ตัวอย่างโค้ดนี้ใช้ AbortController
เพื่อยกเลิกคำขอที่อยู่ระหว่างดำเนินการ คำขอที่อยู่ระหว่างดำเนินการคือคำขอเครือข่ายที่เริ่มดำเนินการแล้วแต่ยังไม่เสร็จสมบูรณ์
สถานการณ์ที่คุณอาจต้องยกเลิกคำขอที่อยู่ระหว่างดำเนินการอาจแตกต่างกันไป แต่ท้ายที่สุดแล้วขึ้นอยู่กับ Use Case และสภาพแวดล้อมของคุณ โค้ดต่อไปนี้แสดงวิธีส่ง AbortSignal
ไปยัง Fetch API AbortSignal
แนบอยู่กับ AbortController
และ AbortController
มีเมธอด abort()
ซึ่งบ่งบอกให้เบราว์เซอร์ยกเลิกคําขอเครือข่าย
const controller = new AbortController();
const signal = controller.signal;
// Cancel the fetch request in 500ms
setTimeout(() => controller.abort(), 500);
try {
const url = 'https://httpbin.org/delay/1';
const response = await fetch(url, { signal });
console.log(response);
} catch (error) {
// DOMException: The user aborted a request.
console.log('Error: ', error)
}
บทสรุป
สิ่งสำคัญอย่างหนึ่งในการจัดการข้อผิดพลาดคือการระบุส่วนต่างๆ ที่อาจทำให้เกิดข้อผิดพลาด ตรวจสอบว่าคุณมีทางเลือกสำรองที่เหมาะสมสำหรับผู้ใช้สำหรับแต่ละสถานการณ์ ถามตัวเองด้วยคำถามต่อไปนี้เกี่ยวกับคำขอดึงข้อมูล
- จะเกิดอะไรขึ้นหากเซิร์ฟเวอร์เป้าหมายหยุดทำงาน
- จะเกิดอะไรขึ้นหากการดึงข้อมูลได้รับการตอบกลับที่ไม่คาดคิด
- จะเกิดอะไรขึ้นหากการเชื่อมต่ออินเทอร์เน็ตของผู้ใช้ไม่สำเร็จ
คุณยังร่างผังงานที่อธิบายฟังก์ชันการทำงานและอินเทอร์เฟซผู้ใช้สำหรับสถานการณ์ต่างๆ ได้ด้วย ทั้งนี้ขึ้นอยู่กับความซับซ้อนของหน้าเว็บ