Bài viết này minh hoạ một số phương pháp xử lý lỗi khi làm việc với Fetch API. API Tìm nạp cho phép bạn gửi yêu cầu đến một tài nguyên mạng từ xa. Khi bạn thực hiện lệnh gọi mạng từ xa, trang web của bạn có thể gặp nhiều lỗi mạng.
Các phần sau đây mô tả các lỗi có thể xảy ra và cách viết mã cung cấp chức năng hợp lý, có khả năng chống chịu lỗi và các điều kiện mạng không mong muốn. Mã có khả năng phục hồi giúp người dùng hài lòng và duy trì mức độ dịch vụ tiêu chuẩn cho trang web của bạn.
Dự đoán các lỗi mạng có thể xảy ra
Phần này mô tả một tình huống trong đó người dùng tạo một video mới có tên "My Travels.mp4"
, sau đó cố gắng tải video đó lên một trang web chia sẻ video.
Khi làm việc với tính năng Tìm nạp, bạn có thể dễ dàng xem xét luồng thành công, trong đó người dùng tải video lên thành công. Tuy nhiên, có những lộ trình khác không suôn sẻ như vậy nhưng nhà phát triển web phải lên kế hoạch. Những đường dẫn (không mong muốn) như vậy có thể xảy ra do lỗi của người dùng, do điều kiện môi trường không mong muốn hoặc do lỗi trên trang web chia sẻ video.
Ví dụ về lỗi người dùng
- Người dùng tải tệp hình ảnh (chẳng hạn như JPEG) lên thay vì tệp video.
- Người dùng bắt đầu tải tệp video không đúng lên. Sau đó, trong quá trình tải lên, người dùng chỉ định đúng tệp video để tải lên.
- Người dùng vô tình nhấp vào "Huỷ tải lên" trong khi video đang tải lên.
Ví dụ về các thay đổi về môi trường
- Kết nối Internet bị ngắt trong khi tải video lên.
- Trình duyệt khởi động lại trong khi tải video lên.
- Máy chủ của trang web chia sẻ video khởi động lại trong khi video đang tải lên.
Ví dụ về lỗi liên quan đến trang web chia sẻ video
- Trang web chia sẻ video không thể xử lý tên tệp có khoảng trắng. Thay vì
"My Travels.mp4"
, lớp này sẽ yêu cầu một tên như"My_Travels.mp4"
hoặc"MyTravels.mp4"
. - Trang web chia sẻ video không thể tải video lên vì video đó vượt quá kích thước tệp tối đa được chấp nhận.
- Trang web chia sẻ video không hỗ trợ bộ mã hoá và giải mã video trong video bạn tải lên.
Những ví dụ này có thể và đã xảy ra trong thực tế. Có thể bạn đã gặp phải những ví dụ như vậy trước đây! Hãy chọn một ví dụ từ mỗi danh mục trước đó và thảo luận về các điểm sau:
- Hành vi mặc định là gì nếu dịch vụ chia sẻ video không thể xử lý ví dụ đã cho?
- Người dùng mong đợi điều gì sẽ xảy ra trong ví dụ này?
- Chúng tôi có thể cải thiện quy trình này bằng cách nào?
Xử lý lỗi bằng API Tìm nạp
Xin lưu ý rằng các ví dụ về mã sau đây sử dụng await
cấp cao nhất (hỗ trợ trình duyệt) vì tính năng này có thể đơn giản hoá mã của bạn.
Khi Fetch API gửi lỗi
Ví dụ này sử dụng câu lệnh khối try
/catch
để phát hiện mọi lỗi được gửi trong khối try
. Ví dụ: nếu Fetch API không thể tìm nạp tài nguyên đã chỉ định, thì lỗi sẽ xảy ra. Trong một khối catch
như thế này, hãy cẩn thận để mang lại trải nghiệm có ý nghĩa cho người dùng. Nếu một vòng quay (spinner), một giao diện người dùng phổ biến đại diện cho một số tiến trình, được hiển thị cho người dùng, thì bạn có thể thực hiện các thao tác sau trong khối catch
:
- Xoá trình đơn vòng quay khỏi trang.
- Cung cấp thông báo hữu ích giải thích vấn đề đã xảy ra và những lựa chọn mà người dùng có thể thực hiện.
- Dựa trên các tuỳ chọn có sẵn, hãy hiển thị nút "Thử lại" cho người dùng.
- Ở chế độ nền, hãy gửi thông tin chi tiết về lỗi đến dịch vụ theo dõi lỗi hoặc đến phần phụ trợ. Thao tác này sẽ ghi lại lỗi để có thể chẩn đoán lỗi ở giai đoạn sau.
try {
const response = await fetch('https://website');
} catch (error) {
// TypeError: Failed to fetch
console.log('There was an error', error);
}
Ở giai đoạn sau, trong khi chẩn đoán lỗi mà bạn đã ghi lại, bạn có thể viết một trường hợp kiểm thử để phát hiện lỗi đó trước khi người dùng nhận thấy có gì đó không ổn. Tuỳ thuộc vào lỗi, kiểm thử có thể là kiểm thử đơn vị, tích hợp hoặc chấp nhận.
Khi mã trạng thái mạng biểu thị lỗi
Mã ví dụ này gửi yêu cầu đến một dịch vụ kiểm thử HTTP luôn phản hồi bằng mã trạng thái HTTP 429 Too Many Requests
. Điều thú vị là phản hồi không đến được khối catch
. Trạng thái 404, cùng với một số mã trạng thái khác, không trả về lỗi mạng mà thay vào đó sẽ phân giải bình thường.
Để kiểm tra xem mã trạng thái HTTP có thành công hay không, bạn có thể sử dụng bất kỳ tuỳ chọn nào sau đây:
- Sử dụng thuộc tính
Response.ok
để xác định xem mã trạng thái có nằm trong phạm vi từ200
đến299
hay không. - Sử dụng thuộc tính
Response.status
để xác định xem phản hồi có thành công hay không. - Sử dụng siêu dữ liệu bất kỳ khác, chẳng hạn như
Response.headers
, để đánh giá xem phản hồi có thành công hay không.
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}`)
}
Tốt nhất là bạn nên làm việc với những người trong tổ chức và nhóm của mình để tìm hiểu các mã trạng thái phản hồi HTTP có thể xảy ra. Đôi khi, các nhà phát triển phụ trách phần phụ trợ, bộ phận vận hành dành cho nhà phát triển và kỹ sư dịch vụ có thể cung cấp thông tin chi tiết độc đáo về các trường hợp hiếm gặp mà bạn có thể không lường trước được.
Khi xảy ra lỗi phân tích cú pháp phản hồi mạng
Ví dụ về mã này minh hoạ một loại lỗi khác có thể xảy ra khi phân tích cú pháp nội dung phản hồi. Giao diện Response
cung cấp các phương thức thuận tiện để phân tích cú pháp nhiều loại dữ liệu, chẳng hạn như văn bản hoặc JSON. Trong mã sau, một yêu cầu mạng được gửi đến một dịch vụ kiểm thử HTTP trả về một chuỗi HTML làm nội dung phản hồi. Tuy nhiên, hệ thống sẽ cố gắng phân tích cú pháp nội dung phản hồi dưới dạng JSON, dẫn đến lỗi.
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);
}
Bạn phải chuẩn bị mã để xử lý nhiều định dạng phản hồi và xác minh rằng phản hồi không mong muốn không làm hỏng trang web cho người dùng.
Hãy xem xét trường hợp sau: Bạn có một tài nguyên từ xa trả về phản hồi JSON hợp lệ và tài nguyên này được phân tích cú pháp thành công bằng phương thức Response.json()
. Dịch vụ có thể ngừng hoạt động. Sau khi ngừng hoạt động, hệ thống sẽ trả về 500 Internal Server Error
. Nếu không sử dụng các kỹ thuật xử lý lỗi thích hợp trong quá trình phân tích cú pháp JSON, thì điều này có thể làm hỏng trang cho người dùng vì một lỗi chưa được xử lý sẽ được gửi.
Khi phải huỷ yêu cầu mạng trước khi yêu cầu đó hoàn tất
Mã ví dụ này sử dụng AbortController
để huỷ một yêu cầu đang diễn ra. Yêu cầu đang diễn ra là một yêu cầu mạng đã bắt đầu nhưng chưa hoàn tất.
Có nhiều trường hợp bạn có thể cần huỷ yêu cầu đang xử lý, nhưng cuối cùng điều này phụ thuộc vào trường hợp sử dụng và môi trường của bạn. Mã sau đây minh hoạ cách truyền AbortSignal
đến API Tìm nạp. AbortSignal
được đính kèm vào AbortController
và AbortController
bao gồm phương thức abort()
, cho trình duyệt biết rằng yêu cầu mạng sẽ bị huỷ.
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)
}
Kết luận
Một khía cạnh quan trọng trong việc xử lý lỗi là xác định các phần có thể gặp lỗi. Đối với mỗi trường hợp, hãy đảm bảo bạn có phương án dự phòng phù hợp cho người dùng. Đối với yêu cầu tìm nạp, hãy tự đặt ra những câu hỏi như:
- Điều gì sẽ xảy ra nếu máy chủ đích gặp sự cố?
- Điều gì sẽ xảy ra nếu Fetch nhận được phản hồi không mong muốn?
- Điều gì sẽ xảy ra nếu kết nối Internet của người dùng không thành công?
Tuỳ thuộc vào độ phức tạp của trang web, bạn cũng có thể phác thảo một sơ đồ quy trình mô tả chức năng và giao diện người dùng cho nhiều tình huống.