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 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 lý do 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 các trình 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 dễ thực hiện cho các nhà phát triể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 xử lý sự kiện tải. Khi sự kiện tải kích hoạt, trình 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 navigator cung cấp phản hồi boolean (đúng hoặc sai). Để kết thúc hành động của người 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 từ navigator? Chà, nó liên quan đến trình duyệt Netscape Navigator từ những năm 90.
Căn giữa phần tử h1 trong trang HTML của bạn với id là “status”. Nếu bạn áp dụng mã JavaScript ở trên vào 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 tải trang. Hãy thêm các trình xử lý sự kiện trực tuyến và ngoại 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 để đặt 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 màn hình 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 navigator và các sự kiện trực tuyến và ngoại tuyến, chúng tôi nhận thấy có sự cố.
Tìm kiếm navigator.onLine trên CanIUse.com cho thấy 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 phần 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”.
Hmm, điều đó gây khó khăn cho công việc 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ể cho 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 navigator làm giải pháp phát hiện kết nối Internet. Đó là một giải pháp có thể tàn phá các ứng dụng của chúng ta vốn phụ thuộc vào việc biết khi nào có nguồn dữ liệu bên ngoài.
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 lũy tiến 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.”
Một tìm kiếm web nhanh chóng cho “navigator trực tuyến không hoạt động” tiết lộ các bài đăng trên diễn đàn khác nhau mà những bài đăng 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 duyên dáng bằng cách 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 sẽ 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 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 để đạt được 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 checkOnlineStatus. Hàm sẽ trả về true hoặc false giống như thuộc tính trực tuyến của navigator.
Bên trong chức năng, chúng tôi sẽ thiết lập một khối thử trong đó chúng tôi đang 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ớ cache.
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 để 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 catch để 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 ta sẽ sử dụng phương thức setInterval và chuyển cho nó một hàm async ẩn danh. Chức năng async sẽ chờ kết quả của chức năng 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 độ trễ khoảng thời gian là 3 giây một lần (3000 mili giây). Điều này thực sự là quá thường xuyên, mặc dù. Kiểm tra 30 giây một lần (30000 mili giây) có thể đủ 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 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 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ó thể chỉ quan trọng nếu bạn có Ứng dụng web lũy tiến sử dụng nhân viên dịch vụ để có sẵn 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 lắng nghe sự kiện tải mới:
window.addEventListener("load", async (event) => {
const statusDisplay = document.getElementById("status");
statusDisplay.textContent = (await checkOnlineStatus())
? "Online"
: "OFFline";
});
Suy nghĩ cuối cùng
Đoạn mã trên phù hợp để 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 thực hiện yêu cầu dữ liệu quan trọng trong ứng dụng của mình.
Do đó, bạn nên gọi hàm checkOnlineStatus trực tiếp trước 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
}
}
Phần kết luận
Mặc dù navigator.onLine được hỗ trợ rộng rãi, nhưng 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 ta có thực sự được kết nối với Internet hay không. Bằng cách sử dụng Fetch API 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: