คุณสามารถใช้ JavaScript ตรวจสอบว่าแอปเชื่อมต่ออินเทอร์เน็ตอยู่หรือไม่ได้ไหม?
ในบทความนี้ ผมจะให้คำตอบอัปเดตสำหรับคำถามการตรวจจับการเชื่อมต่ออินเทอร์เน็ต (พูดเร็ว 5 ครั้งดูสิ!)
วิธีแก้จะใช้ Fetch API ของ JavaScript และโค้ด Asynchronous ด้วย Async & Await แต่ก่อน มาดูวิธีที่ยอมรับทั่วไป และอภิปรายว่าทำไมอาจไม่ใช่ตัวเลือกที่ดีสำหรับแอปของคุณ
navigator.onLine
คุณสมบัติ online ของอินเทอร์เฟซ navigator คือ navigator.onLine ใช้บ่อยในการตรวจสอบสถานะออนไลน์/ออฟไลน์ของเบราว์เซอร์
รวมกับ Event Listener สำหรับเหตุการณ์ online และ offline ดูเหมือนให้โซลูชันง่ายสำหรับนักพัฒนาที่นำไปใช้ได้ง่าย
มาดูวิธีการนำ navigator.onLine ไปใช้
เริ่มด้วยการเพิ่ม Load Event Listener เมื่อเหตุการณ์ load ทำงาน Listener จะตรวจสอบคุณสมบัติ online ของ navigator และแสดงสถานะออนไลน์
คุณสมบัติ online ของ navigator ให้ค่า Boolean (true หรือ false) เพื่อจบการทำงานของ Listener เราจะใช้ Ternary Statement ตั้งค่าการแสดงสถานะ
window.addEventListener("load", (event) => { const statusDisplay = document.getElementById("status"); statusDisplay.textContent = navigator.onLine ? "Online" : "OFFline"; });ทำไมถึงชื่อ navigator? เพราะอ้างอิงเบราว์เซอร์ Netscape Navigator ในทศวรรษ 90
วาง h1 อยู่กลางหน้า HTML พร้อม id "status" ถ้านำโค้ด JavaScript ข้างต้นไปใช้ ควรเห็นแสดง "Online"
แต่นี้อัปเดต h1 เฉพาะตอนโหลดหน้า มาเพิ่ม Event Listener สำหรับ offline และ online เพื่ออัปเดตสถานะทุกครั้งที่เหตุการณ์เหล่านี้เกิด
window.addEventListener("offline", (event) => { const statusDisplay = document.getElementById("status"); statusDisplay.textContent = "OFFline"; }); window.addEventListener("online", (event) => { const statusDisplay = document.getElementById("status"); statusDisplay.textContent = "Online"; });ไปที่แท็บ Application ใน Chrome Dev Tools คลิก ServiceWorker ตั้งค่าเบราว์เซอร์ตอบสนองเหมือนออฟไลน์
ติ๊กและยกเลิกติ๊ก Checkbox Offline หลายครั้ง ควรเห็นการแสดงสถานะตอบสนองทันทีต่อเหตุการณ์ offline และ online ที่ยิงออกมา

มาเจาะลึกลงไปอีกนิด
ต印象แรก ดูเหมือนโซลูชันดีและง่าย แต่เมื่ออ่านเพิ่มเติมเกี่ยวกับคุณสมบัติ online ของ navigator และเหตุการณ์ online/offline จะพบปัญหา
ค้นหา navigator.onLine บน CanIUse.com แสดงการรองรับกว้างขวาง แต่ดูบันทึกใต้ตารางรองรับ จะเห็นว่า
"Online ไม่ได้หมายถึงการเชื่อมต่ออินเทอร์เน็ตเสมอไป อาจแค่หมายถึงการเชื่อมต่อเครือข่ายบางเครือข่าย"
ฮึม นี่ทำให้เรื่องซับซ้อนขึ้น
ดังนั้นถ้าอยากทราบสถานะออนไลน์ของเบราว์เซอร์จริง ควรพัฒนาวิธีตรวจสอบเพิ่มเติม
มาดูเอกสารอ้างอิง MDN สำหรับ navigator.onLine MDN ยืนยันข้อมูล CanIUse และเพิ่มบันทึก
"เบราว์เซอร์นำคุณสมบัตินี้ไปใช้ต่างกัน... ไม่สามารถสมมติได้ว่าค่า true หมายถึงเบราว์เซอร์เข้าถึงอินเทอร์เน็ตได้ อาจได้ false positives..."
ยืนยันความกังวลเกี่ยวกับการใช้คุณสมบัติ online ของ navigator เป็นโซลูชันตรวจจับการเชื่อมต่ออินเทอร์เน็ต โซลูชันนี้อาจทำลายแอปที่พึ่งพาการรู้ว่าแหล่งข้อมูลภายนอกพร้อมใช้งาน
ตัวอย่างหนึ่งคือตอนพยายามกำหนดว่า Progressive Web App ออนไลน์หรือไม่ MDN แนะนำว่า
"...ถ้าอยากทราบสถานะออนไลน์ของเบราว์เซอร์จริง ควรพัฒนาวิธีตรวจสอบเพิ่มเติม"
ค้นหาเว็บ "navigator online not working" จะพบกระทู้ฟอรัมมากมายที่พึ่งพาคุณสมบัตินี้แล้วเจอปัญหา
โซลูชันคืออะไร?
เราต้องรู้ว่าแอปพลิเคชันเชื่อมต่ออินเทอร์เน็ตจริง ไม่ใช่แค่เราเตอร์หรือเครือข่ายท้องถิ่น กลับไปที่ไฟล์ JavaScript เริ่มใหม่
ไอเดียคือสร้างคำขอ และจัดการอย่างสงบด้วย Error Catching ถ้าล้มเหลว ถ้าคำขอสำเร็จ = ออนไลน์ ถ้าล้มเหลว = ไม่ออนไลน์
เราจะขอรูปภาพเล็กๆ (1 พิกเซล) ทุกช่วงเวลา (Interval) เพื่อตรวจสอบสถานะออนไลน์ JavaScript สมัยใหม่มี Fetch API และโค้ด Asynchronous ด้วย Async & Await เราจะใช้เครื่องมือเหล่านี้
checkOnlineStatus()
สร้าง Async Arrow Function ชื่อ checkOnlineStatus ฟังก์ชันจะคืนค่า true หรือ false เหมือนคุณสมบัติ online ของ navigator
ภายในฟังก์ชัน ตั้ง Try Block ที่ await คำขอ fetch รูปภาพ 1 พิกเซล ตรวจสอบว่า Service Worker ไม่ได้แคชรูปนี้
รหัสตอบสนอง HTTP ระหว่าง 200-299 แสดงความสำเร็จ เราจะคืนผลลัพธ์การเปรียบเทียบรหัสสถานะ จะเป็น true ถ้ารหัสสถานะ 200-299 และ false ถ้าไม่ใช่
ต้องมี Catch Block จับ Error ถ้าคำขอล้มเหลว คืนค่า false ใน Catch Block เพื่อบ่งชี้ว่าแน่นอนออฟไลน์
const checkOnlineStatus = async () => { try { const online = await fetch("/1pixel.png"); return online.status >= 200 && online.status < 300; // true หรือ false } catch (err) { return false; // แน่นอนออฟไลน์ } };ต่อไป ใช้เมธอด setInterval ส่ง Anonymous Async Function ฟังก์ชันจะ await ผลลัพธ์ของ checkOnlineStatus ใช้ Ternary Statement กับผลลัพธ์เพื่อแสดงสถานะออนไลน์ปัจจุบัน
สำหรับทดสอบ ตั้งหน่วงเวลา Interval ทุก 3 วินาที (3000 มิลลิวินาที) แต่นี่บ่อยเกินไป ตรวจสอบทุก 30 วินาที (30000 มิลลิวินาที) อาจพอสำหรับความต้องการจริง
setInterval(async () => { const result = await checkOnlineStatus(); const statusDisplay = document.getElementById("status"); statusDisplay.textContent = result ? "Online" : "OFFline"; }, 3000); // บ่อยเกินไป ลอง 30000 สำหรับทุก 30 วินาทีบันทึกโค้ดใหม่ กลับไปทดสอบตอบสนองออฟไลน์ที่แท็บ Application ใน Chrome Dev Tools

เกือบลืม Load Event Listener พร้อมฟังก์ชัน Async! การตรวจจับเหตุการณ์ Load อาจสำคัญก็ต่อเมื่อมี Progressive Web App ใช้ Service Worker สำหรับความพร้อมใช้งานออฟไลน์ มิฉะนั้น เว็บเพจ/แอปจะโหลดไม่ได้โดยไม่มีการเชื่อมต่อ
นี่คือ Load Event Listener ใหม่:
window.addEventListener("load", async (event) => { const statusDisplay = document.getElementById("status"); statusDisplay.textContent = (await checkOnlineStatus()) ? "Online" : "OFFline"; });ความคิดเหลือท้าย
โค้ด Interval ข้างต้นดีสำหรับแสดงสถานะการเชื่อมต่อในแอป แต่ผมไม่แนะนำให้พึ่งพาสถานะการเชื่อมต่อที่ตรวจสอบไป 20-30 วินาทีก่อนหน้า ก่อนทำคำขอข้อมูลสำคัญในแอป
ดังนั้น ควรเรียกฟังก์ชัน checkOnlineStatus โดยตรงก่อนคำขอ และประเมินผลลัพธ์ก่อนขอข้อมูล
const yourDataRequestFunction = async () => { const online = await checkOnlineStatus(); if (online) { // ทำคำขอข้อมูล } }สรุป
แม้ navigator.onLine รองรับกว้างขวาง แต่ให้ผลลัพธ์ไม่น่าเชื่อถือเมื่อกำหนดว่าแอปพลิเคชันเชื่อมต่ออินเทอร์เน็ตจริง การใช้ Fetch API และ JavaScript Asynchronous เราสามารถเขียนโซลูชันที่น่าเชื่อถือมากขึ้นได้เร็ว
ลิงก์โค้ด Gist บน GitHub และวิดีโอสอนที่ผมทำไว้: