Sådan kontrolleres internetforbindelsesstatus ved hjælp af Async JavaScript

Kan du bruge JavaScript til at kontrollere, om din app har forbindelse til internettet?

I denne artikel giver jeg et opdateret svar på dette spørgsmål til detektering af internetforbindelse. (Whew! Sig det hurtigt fem gange!)

Løsningen bruger JavaScript's Fetch API og asynkron kode med Async & Await. Men lad os først se på en accepteret løsning og diskutere, hvorfor det måske ikke er det bedste valg til din ansøgning.

navigator.onLine

Onlinegenskaben til navigatorgrænsefladen navigator.onLinebruges ofte til at registrere browserens online- og offline-status.

Kombineret med lyttere til online- og offline-begivenheder ser det ud til at give en enkel løsning til udviklere, der er nem at implementere.

Lad os se på, hvordan vi implementerer navigator.onLine

Start med at tilføje en load-begivenhedslytter. Når indlæsningshændelsen udløses, vil lytteren kontrollere onlineegenskaben for navigatorgrænsefladen og derefter vise online-status.

Navigators onlinegenskab giver et boolesk svar (sandt eller falsk). For at afslutte lytterens handling bruger vi en ternær erklæring til at indstille statusvisningsværdien.

window.addEventListener("load", (event) => { const statusDisplay = document.getElementById("status"); statusDisplay.textContent = navigator.onLine ? "Online" : "OFFline"; });

Så hvorfor ordet navigator? Nå, det er en henvisning til Netscape Navigator-browseren fra 90'erne.

Centrer et h1-element på din HTML-side med id'et "status". Hvis du anvender JavaScript-koden ovenfor på din side, skal du se den vise "Online".

Men dette opdaterer kun h1-elementet, når siden indlæses. Lad os tilføje offline- og onlinebegivenhedslyttere for at opdatere statusvisningen når som helst en af ​​disse begivenheder brænder.

window.addEventListener("offline", (event) => { const statusDisplay = document.getElementById("status"); statusDisplay.textContent = "OFFline"; }); window.addEventListener("online", (event) => { const statusDisplay = document.getElementById("status"); statusDisplay.textContent = "Online"; });

Vi kan gå til fanen Application i Chrome Dev Tools og klikke på ServiceWorker for at indstille browseren til at svare som om den er offline.

Marker og fjern markeringen i afkrydsningsfeltet Offline et par gange. Du skal se statusdisplayet reagere med det samme på de offline- og onlinebegivenheder, der fyres.

Lad os grave lidt dybere

Ved første indtryk virker ovenstående som en god løsning, der er ret enkel. Desværre finder vi ud af, at der er et problem, når vi læser mere om navigatorens online ejendom og online- og offline-begivenhederne.

Søgning efter navigator.onLine på CanIUse.com viser bred støtte til online | offline status, ejendommen giver. Men når vi ser på noterne under supporttabellen, ser vi det

”Online betyder ikke altid forbindelse til internettet. Det kan også bare betyde forbindelse til et eller andet netværk ”.

Hmm, det smider en skruenøgle i værkerne lidt.

Så hvis du virkelig vil bestemme browserens online status, skal du udvikle yderligere metoder til kontrol.

Lad os også se på MDN-dokumentreferencen til navigator.onLine. MDN-webdokumenter sikkerhedskopierer CanIUse.com-oplysningerne og tilføjer yderligere noter.

“Browsere implementerer denne egenskab forskelligt ... du kan ikke antage, at en sand værdi nødvendigvis betyder, at browseren kan få adgang til internettet. Du kan få falske positive ... ”

Og det bekræfter vores frygt for at bruge navigatorens online ejendom som vores løsning til at opdage en internetforbindelse. Det er en løsning, der kan skabe kaos i vores applikationer, der afhænger af at vide, hvornår eksterne datakilder er tilgængelige.

Et sådant eksempel er, når vi prøver at afgøre, om en Progressiv Web-app er online eller ej. MDN anbefaler endda,

"... hvis du virkelig vil bestemme browserens onlinestatus, skal du udvikle yderligere midler til kontrol."

En hurtig websøgning efter "navigator online fungerer ikke" afslører forskellige forumindlæg, hvor dem, der er afhængige af denne egenskab, er stødt på problemer.

Så hvad er løsningen?

Vi har brug for at vide, hvornår vores applikation virkelig er forbundet til internettet og ikke kun en router eller et lokalt netværk. Lad os gå tilbage til vores JavaScript-fil og starte forfra.

Ideen er at fremsætte en anmodning og håndtere den yndefuldt med fejlfangst, hvis den mislykkes. Hvis anmodningen lykkes, er vi online, og hvis den mislykkes, er vi ikke.

Vi vil anmode om et lille billede med et interval for at bestemme online-status. Moderne JavaScript leverer Fetch API og asynkron kode med Async & Await. Vi bruger disse værktøjer til at nå vores mål.

checkOnlineStatus ()

Lad os starte med at oprette en async-pilfunktion ved navn checkOnlineStatus. Funktionen returnerer sandt eller falsk, ligesom navigatorens online ejendom gør.

Inde i funktionen opretter vi en prøveblok, hvor vi afventer en henteanmodning til et billede med en pixel. Sørg for, at din servicearbejder ikke cachelagrer dette billede.

HTTP-svarskoder mellem 200 og 299 angiver succes, og vi returnerer resultatet af sammenligningen af ​​statuskoden. Dette vil være sandt, hvis svarets status er fra 200 til 299 og ellers falsk.

Vi er også nødt til at give en fangstblok, der fanger fejlen, hvis anmodningen mislykkes. Vi returnerer falsk i fangstblokken for at indikere, at vi bestemt er offline, hvis dette sker.

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 } };

Dernæst bruger vi setInterval-metoden og sender den en anonym async-funktion. Async-funktionen afventer resultatet af vores checkOnlineStatus-funktion. Vi bruger derefter en ternær erklæring med resultatet til at vise den aktuelle online status.

For at teste dette eksempel skal du indstille intervalforsinkelsen til hvert 3. sekund (3000 millisekunder). Dette er dog for ofte. Kontrol hvert 30. sekund (30000 millisekunder) kan være nok til dine faktiske behov.

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

Med vores nye kode gemt, lad os besøge fanen Applikation i Chrome Dev Tools for at teste offline svaret.

I almost forgot to include the load event listener with async functionality! The load event detection is probably only important if you have a Progressive Web App utilizing a service worker for offline availability. Otherwise, your web page or app simply won't load without a connection.

Here's the new load event listener:

window.addEventListener("load", async (event) => { const statusDisplay = document.getElementById("status"); statusDisplay.textContent = (await checkOnlineStatus()) ? "Online" : "OFFline"; });

A Final Thought

The above interval code is good for displaying a connection status in your app. That said, I don't suggest relying on a connection status that was checked 20 or 30 seconds prior to making a critical data request in your application.

Therefore, you should call the checkOnlineStatus function directly prior to the request and evaluate the response before requesting data.

const yourDataRequestFunction = async () => { const online = await checkOnlineStatus(); if (online) { // make data request } }

Conclusion

Mens navigator.onLine understøttes bredt, giver det upålidelige resultater, når det afgøres, om vores applikationer virkelig er forbundet til internettet. Ved hjælp af Fetch API og asynkron JavaScript kan vi hurtigt kode en mere pålidelig løsning.

Her er et link til kodens kerne på GitHub, og her er en video tutorial, jeg sammensatte: