Bagaimana cara mendeteksi acara online / offline lintas-browser?

111

Saya mencoba mendeteksi secara akurat saat browser offline, menggunakan acara online dan offline HTML5.

Ini kode saya:

<script>
    // FIREFOX
    $(window).bind("online", applicationBackOnline); 
    $(window).bind("offline", applicationOffline);

    //IE
    window.onload = function() {
        document.body.ononline = IeConnectionEvent;
        document.body.onoffline = IeConnectionEvent;
    } 
</script>

Ini berfungsi dengan baik ketika saya hanya menekan "Bekerja offline" di Firefox atau IE, tetapi ini bekerja secara acak ketika saya benar-benar mencabut kabelnya.

Apa cara terbaik untuk mendeteksi perubahan ini? Saya ingin menghindari panggilan ajax berulang dengan batas waktu.

Pierre Duplouy
sumber
2
Saya setuju dengan Trefex, tetapi saya juga ingin menambahkan bahwa dukungan deteksi koneksi paling buruk untuk sebagian besar aplikasi: hanya karena kabel dicabut tidak langsung berarti koneksi terputus. Mengandalkan metode yang tidak menguji secara fisik apakah koneksi terbuka tidak dapat menjamin hasil yang akurat.
mattbasta
Terima kasih atas saranmu. Jadi Anda akan merekomendasikan metode Ajax? yaitu. terus mengirim panggilan XHR dengan batas waktu?
Pierre Duplouy
Implementasi Firefox (dan IE dan Opera) salah. Lihat komentar saya untuk efek itu di sini: bugzilla.mozilla.org/show_bug.cgi?id=654579#c9
thewoolleyman
4
Anda mungkin ingin melihat Offline.js , pustaka sumber terbuka yang dibuat hanya untuk tujuan ini.
Adam

Jawaban:

70

Vendor browser tidak dapat menyetujui tentang cara mendefinisikan offline. Beberapa browser memiliki fitur Bekerja Offline, yang mereka anggap terpisah dari kurangnya akses jaringan, yang sekali lagi berbeda dengan akses internet. Semuanya berantakan. Beberapa vendor browser memperbarui flag navigator.onLine ketika akses jaringan yang sebenarnya hilang, yang lainnya tidak.

Dari spesifikasi:

Menampilkan false jika agen pengguna benar-benar offline (terputus dari jaringan). Mengembalikan nilai benar jika agen pengguna mungkin online.

Peristiwa online dan offline dijalankan ketika nilai atribut ini berubah.

Atribut navigator.onLine harus mengembalikan false jika agen pengguna tidak akan menghubungi jaringan ketika pengguna mengikuti tautan atau ketika skrip meminta halaman jarak jauh (atau tahu bahwa upaya seperti itu akan gagal), dan harus mengembalikan true jika tidak.

Akhirnya, spesifikasi mencatat:

Atribut ini secara inheren tidak dapat diandalkan. Komputer dapat terhubung ke jaringan tanpa memiliki akses Internet.

Rebecca
sumber
23
Hanya Chrome yang menyetel navigator.onLine dengan benar saat konektivitas hilang. Baik Safari dan Firefox tidak pernah menyetel bendera ke false jika Anda menghapus koneksi internet.
chovy
2
@chovy dan bagaimana dengan sekarang? Saya baru-baru ini mengujinya di Firefox / Chrome dan mendapatkan hasil yang diharapkan, melihat bahwa benderanya disetel, ketika saya mematikan dan pada koneksi internet ..
James Cazzetta
12
Hari ini 31/1/2017 saya membuka OSX Chrome 55.0.2883.95, Safari 10.0.3, dan FF 50.1.0. Semua window.navigator.onLine tampaknya berfungsi dengan baik ketika saya tetap berada di jaringan saya, tetapi mencabut kabel dari router saya. Mereka semua terdeteksi offline dengan benar.
nycynik
3
navigator.onLine didukung di semua browser utama (dan telah berlangsung selama beberapa waktu): caniuse.com/#feat=online-status
Rafael Lüder
@ RafaelLück Benar pada hari ini, tetapi jawaban ini ditulis pada Jan 2011!
Rebecca
34

Vendor browser utama berbeda dalam arti "offline".

Chrome dan Safari akan mendeteksi saat Anda "offline" secara otomatis - artinya acara dan properti "online" akan aktif secara otomatis saat Anda mencabut kabel jaringan.

Firefox (Mozilla), Opera, dan IE menggunakan pendekatan yang berbeda, dan menganggap Anda "online" kecuali Anda secara eksplisit memilih "Mode Offline" di browser - meskipun Anda tidak memiliki sambungan jaringan yang berfungsi.

Ada argumen yang valid untuk perilaku Firefox / Mozilla, yang diuraikan dalam komentar laporan bug ini:

https://bugzilla.mozilla.org/show_bug.cgi?id=654579

Namun, untuk menjawab pertanyaan - Anda tidak dapat mengandalkan acara / properti online / offline untuk mendeteksi apakah sebenarnya ada konektivitas jaringan.

Sebaliknya, Anda harus menggunakan pendekatan alternatif.

Bagian "Catatan" dari artikel Pengembang Mozilla ini menyediakan tautan ke dua metode alternatif:

https://developer.mozilla.org/en/Online_and_offline_events

"Jika API tidak diterapkan di browser, Anda dapat menggunakan sinyal lain untuk mendeteksi apakah Anda sedang offline termasuk mendengarkan peristiwa kesalahan AppCache dan respons dari XMLHttpRequest"

Ini menautkan ke contoh pendekatan "mendengarkan peristiwa kesalahan AppCache":

http://www.html5rocks.com/en/mobile/workingoffthegrid/#toc-appcache

... dan contoh pendekatan "mendeteksi kegagalan XMLHttpRequest":

http://www.html5rocks.com/en/mobile/workingoffthegrid/#toc-xml-http-request

HTH, - Cad

thewoolleyman
sumber
1
Dimulai dengan Firefox 41: updates this property when the OS reports a change in network connectivity on Windows, Linux, and OS X.(menurut dokumen yang Anda sebutkan). Jadi tidak hanya offline jika Anda menjelajah dengan browser "mode Offline"
Bung
17

Saat ini ada pustaka JavaScript open source yang melakukan pekerjaan ini: disebut Offline.js.

Secara otomatis menampilkan indikasi online / offline kepada pengguna Anda.

https://github.com/HubSpot/offline

Pastikan untuk memeriksa README lengkap . Ini berisi acara yang bisa Anda ikuti.

Ini halaman uji . Ini indah / memiliki UI umpan balik yang bagus! :)

Offline.js Simulate UI adalah plugin Offline.js yang memungkinkan Anda menguji bagaimana halaman Anda merespons status konektivitas yang berbeda tanpa harus menggunakan metode brute-force untuk menonaktifkan konektivitas Anda yang sebenarnya.

Leniel Maccaferri
sumber
2
Perpustakaan sebenarnya bekerja dengan mengambil favicon lokal berulang kali di bawah tenda. Menurut saya, perpustakaan itu terlalu "besar" dan memiliki terlalu banyak fitur; Trik utamanya hanya mengambil favicon secara berulang-ulang.
Karel Bílek
1
Tidak mendeteksi offline ketika saya mencabut kabel jaringan
poshest
15

Cara terbaik yang bekerja sekarang di semua Browser Utama adalah dengan Script berikut:

(function () {
    var displayOnlineStatus = document.getElementById("online-status"),
        isOnline = function () {
            displayOnlineStatus.innerHTML = "Online";
            displayOnlineStatus.className = "online";
        },
        isOffline = function () {
            displayOnlineStatus.innerHTML = "Offline";
            displayOnlineStatus.className = "offline";
        };

    if (window.addEventListener) {
        /*
            Works well in Firefox and Opera with the 
            Work Offline option in the File menu.
            Pulling the ethernet cable doesn't seem to trigger it.
            Later Google Chrome and Safari seem to trigger it well
        */
        window.addEventListener("online", isOnline, false);
        window.addEventListener("offline", isOffline, false);
    }
    else {
        /*
            Works in IE with the Work Offline option in the 
            File menu and pulling the ethernet cable
        */
        document.body.ononline = isOnline;
        document.body.onoffline = isOffline;
    }
})();

Sumber: http://robertnyman.com/html5/offline/online-offline-events.html

tmaximini.dll
sumber
3
Seperti komentar dalam kode itu sendiri dengan jelas menyatakan - itu tidak berfungsi di Firefox / Chrome jika Anda mencabut kabel ethernet atau mematikan wifi.
Manish
Saya mencoba mengunjungi tautan "Sumber" dan kabel ethernet terputus, itu menunjukkan "Anda sedang offline" di IE, tetapi tidak di Firefox / Chrome untuk saya (menggunakan versi terbaru dari semua browser). Mungkinkah saya melewatkan sesuatu?
Manish
13

Sejak baru-baru ini, navigator.onLinemenunjukkan hal yang sama di semua browser utama, dan dengan demikian dapat digunakan.

if (navigator.onLine) {
  // do things that need connection
} else {
  // do things that don't need connection
}

Versi terlama yang mendukung ini dengan cara yang benar adalah: Firefox 41 , IE 9, Chrome 14 dan Safari 5.

Saat ini ini akan mewakili hampir seluruh spektrum pengguna, tetapi Anda harus selalu memeriksa kemampuan apa yang dimiliki pengguna laman Anda.

Sebelum FF 41, itu hanya akan ditampilkan falsejika pengguna meletakkan browser secara manual dalam mode offline. Di IE 8, properti berada di body, bukan window.

sumber: caniuse

Haroen Viaene
sumber
11

The window.navigator.onLineatribut dan peristiwa yang terkait saat ini tidak dapat diandalkan pada browser web tertentu ( terutama Firefox desktop yang ) seperti dikatakan @Junto, jadi aku menulis fungsi kecil (menggunakan jQuery) yang memeriksa secara berkala status konektivitas jaringan dan meningkatkan sesuai offlinedan onlineacara:

// Global variable somewhere in your app to replicate the 
// window.navigator.onLine variable (it is not modifiable). It prevents
// the offline and online events to be triggered if the network
// connectivity is not changed
var IS_ONLINE = true;

function checkNetwork() {
  $.ajax({
    // Empty file in the root of your public vhost
    url: '/networkcheck.txt',
    // We don't need to fetch the content (I think this can lower
    // the server's resources needed to send the HTTP response a bit)
    type: 'HEAD',
    cache: false, // Needed for HEAD HTTP requests
    timeout: 2000, // 2 seconds
    success: function() {
      if (!IS_ONLINE) { // If we were offline
        IS_ONLINE = true; // We are now online
        $(window).trigger('online'); // Raise the online event
      }
    },
    error: function(jqXHR) {
      if (jqXHR.status == 0 && IS_ONLINE) {
        // We were online and there is no more network connection
        IS_ONLINE = false; // We are now offline
        $(window).trigger('offline'); // Raise the offline event
      } else if (jqXHR.status != 0 && !IS_ONLINE) {
        // All other errors (404, 500, etc) means that the server responded,
        // which means that there are network connectivity
        IS_ONLINE = true; // We are now online
        $(window).trigger('online'); // Raise the online event
      }
    }
  });
}

Anda bisa menggunakannya seperti ini:

// Hack to use the checkNetwork() function only on Firefox 
// (http://stackoverflow.com/questions/5698810/detect-firefox-browser-with-jquery/9238538#9238538)
// (But it may be too restrictive regarding other browser
// who does not properly support online / offline events)
if (!(window.mozInnerScreenX == null)) {
    window.setInterval(checkNetwork, 30000); // Check the network every 30 seconds
}

Untuk mendengarkan acara offline dan online (dengan bantuan jQuery):

$(window).bind('online offline', function(e) {
  if (!IS_ONLINE || !window.navigator.onLine) {
    alert('We have a situation here');
  } else {
    alert('Battlestation connected');
  }
});
Epoc
sumber
7

navigator.onLine berantakan

Saya menghadapi ini ketika mencoba melakukan panggilan ajax ke server.

Ada beberapa kemungkinan situasi ketika klien sedang offline:

  • waktu panggilan ajax dan Anda menerima kesalahan
  • panggilan ajax kembali sukses, tapi pesannya null
  • panggilan ajax tidak dijalankan karena browser memutuskan demikian (mungkin ini adalah saat navigator.onLine menjadi salah setelah beberapa saat)

Solusi yang saya gunakan adalah mengontrol status diri saya dengan javascript. Saya mengatur kondisi panggilan yang berhasil, dalam hal lain saya menganggap klien sedang offline. Sesuatu seperti ini:

var offline;
pendingItems.push(item);//add another item for processing
updatePendingInterval = setInterval("tryUpdatePending()",30000);
tryUpdatePending();

    function tryUpdatePending() {

        offline = setTimeout("$('#offline').show()", 10000);
        $.ajax({ data: JSON.stringify({ items: pendingItems }), url: "WebMethods.aspx/UpdatePendingItems", type: "POST", dataType: "json", contentType: "application/json; charset=utf-8",
          success: function (msg) {
            if ((!msg) || msg.d != "ok")
              return;
            pending = new Array(); //empty the pending array
            $('#offline').hide();
            clearTimeout(offline);
            clearInterval(updatePendingInterval);
          }
        });
      }
Toolkit
sumber
5

Di HTML5 Anda dapat menggunakan navigator.onLineproperti. Lihat di sini:

http://www.w3.org/TR/offline-webapps/#related

Mungkin perilaku Anda saat ini acak karena javascript hanya menyiapkan variabel "browser" dan kemudian mengetahui apakah Anda sedang offline dan online, tetapi tidak benar-benar memeriksa Sambungan Jaringan.

Beri tahu kami jika ini yang Anda cari.

Salam,

Trefex
sumber
Terima kasih atas bantuan Anda Trefex. Saya mengubah kode saya, dan sekarang hanya memeriksa properti navigator.onLine, namun saya mendapatkan perilaku yang sama seperti sebelumnya. Silakan lihat komentar mattbasta.
Pierre Duplouy
Hai Pedro, saya setuju dengan mattbasta tetapi saya berharap ini akan berhasil untuk Anda :) Saya pasti akan menggunakan metode Ajax untuk menanyakan beberapa URL yang Anda tahu selalu aktif dan kemudian Anda akan tahu jika koneksi terputus atau tidak. Di catatan lain, mengapa Anda memerlukan deteksi yang akurat untuk status online / offline? Mungkin jika kami mengetahui lebih banyak, akan ada solusi lain untuk masalah Anda. Beri tahu kami,
Trefex
1
Ok, terima kasih :) Saya hanya berpikir akan lebih baik bagi pengguna jika aplikasi dapat mendeteksi secara otomatis perubahan konektivitas (tidak perlu mengaktifkan mode offline secara manual di FF atau IE). Dengan cara ini, saat aplikasi offline, aplikasi akan menggunakan cache lokalnya alih-alih meminta server. Saya menemukan posting ini dari John Resig, yang cukup banyak menjelaskan mengapa ini tidak berhasil: ejohn.org/blog/offline-events
Pierre Duplouy
Terima kasih atas kiriman blog itu. Andalkan analisis mendalam dan langsung ke intinya. Saya pikir apa yang ingin Anda capai adalah yang terbaik jika Anda menanyakan beberapa server (mungkin milik Anda sendiri) dan kemudian beralih ke cache lokal ketika ada x jumlah waktu tunggu. Bagaimana menurut anda ?
Trefex
Ya, saya rasa itu adalah pilihan terbaik - mengingat keadaan seni saat ini. Saya berharap semua browser pada akhirnya dapat mendeteksi sendiri hilangnya koneksi yang sebenarnya: menggunakan navigator.onLine cukup sederhana dan ini seharusnya tidak lebih rumit. Tidakkah menurutmu?
Pierre Duplouy
3

Silakan temukan modul require.js yang saya tulis untuk Offline.

define(['offline'], function (Offline) {
    //Tested with Chrome and IE11 Latest Versions as of 20140412
    //Offline.js - http://github.hubspot.com/offline/ 
    //Offline.js is a library to automatically alert your users 
    //when they've lost internet connectivity, like Gmail.
    //It captures AJAX requests which were made while the connection 
    //was down, and remakes them when it's back up, so your app 
    //reacts perfectly.

    //It has a number of beautiful themes and requires no configuration.
    //Object that will be exposed to the outside world. (Revealing Module Pattern)

    var OfflineDetector = {};

    //Flag indicating current network status.
    var isOffline = false;

    //Configuration Options for Offline.js
    Offline.options = {
        checks: {
            xhr: {
                //By default Offline.js queries favicon.ico.
                //Change this to hit a service that simply returns a 204.
                url: 'favicon.ico'
            }
        },

        checkOnLoad: true,
        interceptRequests: true,
        reconnect: true,
        requests: true,
        game: false
    };

    //Offline.js raises the 'up' event when it is able to reach
    //the server indicating that connection is up.
    Offline.on('up', function () {
        isOffline = false;
    });

    //Offline.js raises the 'down' event when it is unable to reach
    //the server indicating that connection is down.
    Offline.on('down', function () {
        isOffline = true;
    });

    //Expose Offline.js instance for outside world!
    OfflineDetector.Offline = Offline;

    //OfflineDetector.isOffline() method returns the current status.
    OfflineDetector.isOffline = function () {
        return isOffline;
    };

    //start() method contains functionality to repeatedly
    //invoke check() method of Offline.js.
    //This repeated call helps in detecting the status.
    OfflineDetector.start = function () {
        var checkOfflineStatus = function () {
            Offline.check();
        };
        setInterval(checkOfflineStatus, 3000);
    };

    //Start OfflineDetector
    OfflineDetector.start();
    return OfflineDetector;
});

Silakan baca posting blog ini dan beri tahu saya pemikiran Anda. http://zen-and-art-of-programming.blogspot.com/2014/04/html-5-offline-application-development.html Berisi contoh kode menggunakan offline.js untuk mendeteksi ketika klien sedang offline.

Srihari Sridharan
sumber
3
Perhatikan bahwa jawaban link-only tidak disarankan, jawaban SO harus menjadi titik akhir dari pencarian solusi (vs. referensi lain yang berhenti, yang cenderung menjadi basi seiring waktu). Harap pertimbangkan untuk menambahkan sinopsis yang berdiri sendiri di sini, dengan menyimpan tautan sebagai referensi.
kleopatra
Hai, saya telah memposting modul require.js bersama dengan referensi tautan. Terima kasih untuk sarannya.
Srihari Sridharan
2

Anda dapat mendeteksi offline lintas browser dengan mudah seperti di bawah ini

var randomValue = Math.floor((1 + Math.random()) * 0x10000)

$.ajax({
      type: "HEAD",
      url: "http://yoururl.com?rand=" + randomValue,
      contentType: "application/json",
      error: function(response) { return response.status == 0; },
      success: function() { return true; }
   });

Anda dapat mengganti yoururl.com dengan document.location.pathname.

Inti dari solusinya adalah, coba sambungkan ke nama domain Anda, jika Anda tidak dapat tersambung - Anda sedang offline. bekerja lintas browser.

harishr
sumber
mengingat bahwa tidak ada nama url setelah nama domain, tidak ada perubahan untuk mendapatkan 404
harishr
Terkadang tidak, seperti beranda api saya adalah 404
Ben Aubin
bagaimana pentingnya halaman rumah api ?? tidak mengerti. karena ketika masuk ke server, tidak ada url - jadi tidak ada pemrosesan, bahkan jika beranda Anda adalah 404 - tidak masalah. mungkin jika Anda dapat memberikan beberapa kode contoh, yang dapat saya coba dan memahami masalah yang Anda
nyatakan
Bukan hanya api saya, tetapi banyak situs yang tidak memiliki beranda. Periksa untuk memastikan kode status dan data yang diterima adalah nol, itu adalah cara terbaik untuk memastikan itu bukan hanya kesalahan normal yang diharapkan
Ben Aubin
webapi saya juga tidak memiliki halaman muka, tetapi cara di atas tetap berfungsi. itu sebabnya saya bingung. bagaimana halaman rumah penting, mengingat itu berfungsi
harishr
2

Saya menggunakan opsi FALLBACK dalam manifes cache HTML5 untuk memeriksa apakah aplikasi html5 saya online atau offline dengan:

FALLBACK:
/online.txt /offline.txt

Di halaman html saya menggunakan javascript tot membaca konten file txt online / offline:

<script>$.get( "urlto/online.txt", function( data ) {
$( ".result" ).html( data );
alert( data );
});</script>

Saat offline script akan membaca konten offline.txt. Berdasarkan teks di file, Anda dapat mendeteksi jika halaman web online offline.

Marcel Scholte
sumber
0

Inilah solusi saya.

Diuji dengan IE, Opera, Chrome, FireFox, Safari, sebagai Phonegap WebApp di IOS 8 dan sebagai Phonegap WebApp di Android 4.4.2

Solusi ini tidak berfungsi dengan FireFox di localhost.

================================================== ===============================

onlineCheck.js (jalur file: "root / js / onlineCheck.js):

var isApp = false;

function onLoad() {
        document.addEventListener("deviceready", onDeviceReady, false);
}

function onDeviceReady() {
    isApp = true;
    }


function isOnlineTest() {
    alert(checkOnline());
}

function isBrowserOnline(no,yes){
    //Didnt work local
    //Need "firefox.php" in root dictionary
    var xhr = XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHttp');
    xhr.onload = function(){
        if(yes instanceof Function){
            yes();
        }
    }
    xhr.onerror = function(){
        if(no instanceof Function){
            no();
        }
    }
    xhr.open("GET","checkOnline.php",true);
    xhr.send();
}

function checkOnline(){

    if(isApp)
    {
        var xhr = new XMLHttpRequest();
        var file = "http://dexheimer.cc/apps/kartei/neu/dot.png";

        try {
            xhr.open('HEAD', file , false); 
            xhr.send(null);

            if (xhr.status >= 200 && xhr.status < 304) {
                return true;
            } else {
                return false;
            }
        } catch (e) 
        {
            return false;
        }
    }else
    {
        var tmpIsOnline = false;

        tmpIsOnline = navigator.onLine;

        if(tmpIsOnline || tmpIsOnline == "undefined")
        {
            try{
                //Didnt work local
                //Need "firefox.php" in root dictionary
                var xhr = XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHttp');
                xhr.onload = function(){
                    tmpIsOnline = true;
                }
                xhr.onerror = function(){
                    tmpIsOnline = false;
                }
                xhr.open("GET","checkOnline.php",false);
                xhr.send();
            }catch (e){
                tmpIsOnline = false;
            }
        }
        return tmpIsOnline;

    }
}

================================================== ===============================

index.html (jalur file: "root / index.html"):

<!DOCTYPE html>
<html>


<head>
    ...

    <script type="text/javascript" src="js/onlineCheck.js" ></script>

    ...

</head>

...

<body onload="onLoad()">

...

    <div onclick="isOnlineTest()">  
        Online?
    </div>
...
</body>

</html>

================================================== ===============================

checkOnline.php (jalur file: "root"):

<?php echo 'true'; ?> 
JoJoWhatsUp
sumber
0

Menggunakan Badan Dokumen:

<body ononline="onlineConditions()" onoffline="offlineConditions()">(...)</body>

Menggunakan Acara Javascript:

window.addEventListener('load', function() {

  function updateOnlineStatus() {

    var condition = navigator.onLine ? "online" : "offline";
    if( condition == 'online' ){
        console.log( 'condition: online')
    }else{
        console.log( 'condition: offline')
    }

  }

  window.addEventListener('online',  updateOnlineStatus );
  window.addEventListener('offline', updateOnlineStatus );

});

Referensi :
Badan-Dokumen: Acara
Javascript-Acara online : Acara online dan offline

Pemikiran Tambahan:
Untuk mengirim sekitar "koneksi jaringan tidak sama dengan koneksi internet" Masalah dari metode di atas: Anda dapat memeriksa koneksi internet satu kali dengan ajax pada aplikasi start dan mengkonfigurasi mode online / offline. Buat tombol sambungkan kembali agar pengguna dapat online. Dan tambahkan pada setiap permintaan ajax yang gagal fungsi yang menendang pengguna kembali ke mode offline.

Milingu Kilu
sumber
1
Ini tidak akan berhasil: window.addEventListener('online', updateOnlineStatus(event) );karena Anda memanggil fungsi updateOnlineStatus () dengan segera. Seharusnyawindow.addEventListener('online', updateOnlineStatus );
Sébastien Rosset