Bạn có thể sử dụng JavaScript để kiểm tra xem ứng dụng của mình có được kết nối với internet không?
Trong bài viết này, tôi sẽ cung cấp câu trả lời cập nhật cho câu hỏi phát hiện kết nối Internet này. (Chà! Nói nhanh như vậy năm lần!)
Giải pháp sẽ sử dụng API Tìm nạp của JavaScript và mã không đồng bộ với Async &Await. Nhưng trước tiên, hãy xem xét một giải pháp được chấp nhận và thảo luận tại sao nó có thể không phải là lựa chọn tốt nhất cho ứng dụng của bạn.
Navigator.onLine
Thuộc tính trực tuyến của giao diện điều hướng, navigator.onLine
, thường được sử dụng để phát hiện trạng thái trực tuyến và ngoại tuyến của trình duyệt.
Được kết hợp với trình lắng nghe cho các sự kiện trực tuyến và ngoại tuyến, nó dường như cung cấp một giải pháp đơn giản cho các nhà phát triển dễ thực hiện.
Hãy xem cách chúng tôi triển khai Navigator.onLine
Bắt đầu bằng cách thêm trình nghe sự kiện tải. Khi sự kiện tải kích hoạt, người nghe sẽ kiểm tra thuộc tính trực tuyến của giao diện điều hướng và sau đó hiển thị trạng thái trực tuyến.
Thuộc tính trực tuyến của điều hướng cung cấp phản hồi boolean (đúng hoặc sai). Để kết thúc hành động của trình nghe, chúng tôi sẽ sử dụng câu lệnh bậc ba để đặt giá trị hiển thị trạng thái.
window.addEventListener("load", (event) => {
const statusDisplay = document.getElementById("status");
statusDisplay.textContent = navigator.onLine ? "Online" : "OFFline";
});
Vậy tại sao lại dùng từ điều hướng? Chà, đó là tham chiếu đến trình duyệt Netscape Navigator từ những năm 90.
Căn giữa một phần tử h1 trong trang HTML của bạn với id là "trạng thái". Nếu bạn áp dụng mã JavaScript ở trên cho trang của mình, bạn sẽ thấy nó hiển thị “Trực tuyến”.
Nhưng điều này chỉ cập nhật phần tử h1 khi trang tải. Hãy thêm trình nghe sự kiện ngoại tuyến và trực tuyến để cập nhật trạng thái hiển thị bất kỳ lúc nào một trong hai sự kiện đó kích hoạt.
window.addEventListener("offline", (event) => {
const statusDisplay = document.getElementById("status");
statusDisplay.textContent = "OFFline";
});
window.addEventListener("online", (event) => {
const statusDisplay = document.getElementById("status");
statusDisplay.textContent = "Online";
});
Chúng ta có thể chuyển đến tab Ứng dụng của Chrome Dev Tools và nhấp vào ServiceWorker để thiết lập trình duyệt phản hồi như thể nó đang ngoại tuyến.
Chọn và bỏ chọn hộp kiểm Ngoại tuyến một vài lần. Bạn sẽ thấy hiển thị trạng thái phản hồi ngay lập tức với các sự kiện ngoại tuyến và trực tuyến được kích hoạt.
Hãy tìm hiểu sâu hơn một chút
Ở ấn tượng đầu tiên, ở trên có vẻ như là một giải pháp tốt khá đơn giản. Thật không may, khi chúng tôi đọc thêm về thuộc tính trực tuyến của điều hướng và các sự kiện trực tuyến và ngoại tuyến, chúng tôi nhận thấy có một vấn đề.
Tìm kiếm Navigator.onLine trên CanIUse.com cho thấy sự hỗ trợ rộng rãi cho trực tuyến | trạng thái ngoại tuyến mà tài sản cung cấp. Tuy nhiên, nhìn vào ghi chú bên dưới bảng hỗ trợ, chúng ta thấy rằng
“Trực tuyến không phải lúc nào cũng có nghĩa là kết nối với Internet. Nó cũng có thể chỉ có nghĩa là kết nối với một số mạng ”.
Rất tiếc, điều đó làm cho cờ lê hoạt động một chút.
Vì vậy, nếu bạn thực sự muốn xác định trạng thái trực tuyến của trình duyệt, bạn nên phát triển các phương tiện bổ sung để kiểm tra.
Chúng ta cũng hãy xem tham chiếu tài liệu MDN cho Navigator.onLine. Tài liệu web MDN sao lưu thông tin CanIUse.com và thêm ghi chú bổ sung.
“Các trình duyệt triển khai thuộc tính này theo cách khác ... bạn không thể giả định rằng giá trị thực nhất thiết có nghĩa là trình duyệt có thể truy cập internet. Bạn có thể nhận được kết quả dương tính giả ... ”
Và điều đó khẳng định nỗi sợ hãi của chúng tôi về việc sử dụng thuộc tính trực tuyến của điều hướng làm giải pháp phát hiện kết nối Internet của chúng tôi. Đó là một giải pháp có thể tàn phá các ứng dụng của chúng tôi mà phụ thuộc vào việc biết khi nào các nguồn dữ liệu bên ngoài có sẵn.
Một ví dụ như vậy là khi chúng tôi đang cố gắng xác định xem Ứng dụng web tiến bộ có trực tuyến hay không. MDN thậm chí còn khuyến nghị,
“... nếu bạn thực sự muốn xác định trạng thái trực tuyến của trình duyệt, bạn nên phát triển các phương tiện bổ sung để kiểm tra.”
Tìm kiếm nhanh trên web cho “điều hướng trực tuyến không hoạt động” tiết lộ các bài đăng khác nhau trên diễn đàn mà những người phụ thuộc vào thuộc tính này đã gặp sự cố.
Vậy giải pháp là gì?
Chúng tôi cần biết khi nào ứng dụng của chúng tôi thực sự được kết nối với Internet chứ không chỉ là bộ định tuyến hoặc mạng cục bộ. Hãy quay lại tệp JavaScript của chúng tôi và bắt đầu lại.
Ý tưởng là đưa ra một yêu cầu và xử lý nó một cách khéo léo với tính năng bắt lỗi nếu nó không thành công. Nếu yêu cầu thành công, chúng tôi đang trực tuyến và nếu yêu cầu không thành công, chúng tôi sẽ không.
Chúng tôi sẽ yêu cầu một hình ảnh nhỏ trong một khoảng thời gian để xác định trạng thái trực tuyến. JavaScript hiện đại cung cấp API Tìm nạp và mã không đồng bộ với Async &Await. Chúng tôi sẽ sử dụng những công cụ này để hoàn thành mục tiêu của mình.
checkOnlineStatus ()
Hãy bắt đầu bằng cách tạo một hàm mũi tên không đồng bộ có tên là checkOnlineStatus. Hàm sẽ trả về true hoặc false giống như thuộc tính trực tuyến của điều hướng.
Bên trong hàm, chúng tôi sẽ thiết lập khối thử trong đó chúng tôi chờ yêu cầu tìm nạp cho hình ảnh một pixel. Đảm bảo nhân viên dịch vụ của bạn không lưu hình ảnh này vào bộ nhớ đệm.
Mã phản hồi HTTP từ 200 đến 299 cho biết thành công và chúng tôi sẽ trả về kết quả so sánh mã trạng thái. Điều này sẽ đúng nếu trạng thái phản hồi là từ 200 đến 299 và sai nếu ngược lại.
Chúng tôi cũng phải cung cấp một khối bắt lỗi nếu yêu cầu không thành công. Chúng tôi sẽ trả về false trong khối bắt để cho biết chúng tôi chắc chắn đang ngoại tuyến nếu điều này xảy ra.
const checkOnlineStatus = async () => {
try {
const online = await fetch("/1pixel.png");
return online.status >= 200 && online.status < 300; // either true or false
} catch (err) {
return false; // definitely offline
}
};
Tiếp theo, chúng tôi sẽ sử dụng phương thức setInterval và chuyển cho nó một hàm không đồng bộ ẩn danh. Hàm async sẽ chờ kết quả của hàm checkOnlineStatus của chúng tôi. Sau đó, chúng tôi sẽ sử dụng một câu lệnh bậc ba với kết quả để hiển thị trạng thái trực tuyến hiện tại.
Để kiểm tra ví dụ này, hãy đặt khoảng thời gian trễ là 3 giây một lần (3000 mili giây). Tuy nhiên, điều này thực sự quá thường xuyên. Kiểm tra 30 giây một lần (30000 mili giây) có thể là đủ cho nhu cầu thực tế của bạn.
setInterval(async () => {
const result = await checkOnlineStatus();
const statusDisplay = document.getElementById("status");
statusDisplay.textContent = result ? "Online" : "OFFline";
}, 3000); // probably too often, try 30000 for every 30 seconds
Với mã mới của chúng tôi đã được lưu, hãy truy cập lại tab Ứng dụng trong Công cụ dành cho nhà phát triển của Chrome để kiểm tra phản hồi ngoại tuyến.
Tôi gần như đã quên bao gồm trình xử lý sự kiện tải với chức năng không đồng bộ! Việc phát hiện sự kiện tải có lẽ chỉ quan trọng nếu bạn có một Ứng dụng web tiến bộ sử dụng một nhân viên dịch vụ để có tính khả dụng ngoại tuyến. Nếu không, trang web hoặc ứng dụng của bạn sẽ không tải nếu không có kết nối.
Đây là trình xử lý sự kiện tải mới:
window.addEventListener("load", async (event) => {
const statusDisplay = document.getElementById("status");
statusDisplay.textContent = (await checkOnlineStatus())
? "Online"
: "OFFline";
});
Lời kết
Mã khoảng thời gian trên rất tốt để hiển thị trạng thái kết nối trong ứng dụng của bạn. Điều đó nói rằng, tôi không khuyên bạn nên dựa vào trạng thái kết nối đã được kiểm tra 20 hoặc 30 giây trước khi đưa ra yêu cầu dữ liệu quan trọng trong ứng dụng của bạn.
Do đó, bạn nên gọi trực tiếp hàm checkOnlineStatus trước khi yêu cầu và đánh giá phản hồi trước khi yêu cầu dữ liệu.
const yourDataRequestFunction = async () => {
const online = await checkOnlineStatus();
if (online) {
// make data request
}
}
Kết luận
Trong khi Navigator.onLine được hỗ trợ rộng rãi, nó cung cấp các kết quả không đáng tin cậy khi xác định xem các ứng dụng của chúng tôi có thực sự được kết nối với Internet hay không. Bằng cách sử dụng API Tìm nạp và JavaScript không đồng bộ, chúng tôi có thể nhanh chóng mã hóa một giải pháp đáng tin cậy hơn.
Đây là liên kết đến ý chính của mã trên GitHub và đây là video hướng dẫn tôi tổng hợp lại: