オンライン/オフラインイベントのクロスブラウザを検出するにはどうすればよいですか?


111

HTML5のオンラインイベントとオフラインイベントを使用して、ブラウザーがオフラインになったことを正確に検出しようとしています。

これが私のコードです:

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

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

FirefoxまたはIEで「オフラインで作業」を押すだけで問題なく動作しますが、実際にケーブルを抜くとランダムに動作します。

この変化を検出する最良の方法は何ですか?タイムアウトでajax呼び出しを繰り返さないようにしたいと思います。


2
私はTrefexに同意しますが、接続検出のサポートはほとんどのアプリにとって見苦しいものであることも付け加えたいと思います:ワイヤーが外されているからといってすぐに接続が失われるわけではありません。接続が開いているかどうかを物理的にテストしない方法に依存しても、正確な結果を保証することはできません。
mattbasta

アドバイスありがとうございます。Ajaxメソッドをお勧めしますか?すなわち。タイムアウトでXHR呼び出しを送信し続けますか?
Pierre Duplouy、2010

Firefox(およびIEとOpera)の実装は間違っています。その影響についての私のコメントをここで参照してください:bugzilla.mozilla.org/show_bug.cgi
id

4
この目的だけのために構築されたオープンソースライブラリであるOffline.jsをチェックしてみてください。
アダム

回答:


70

ブラウザーベンダーは、オフラインの定義方法に同意できません。一部のブラウザーにはオフライン作業機能があり、ネットワークアクセスの欠如とは別に、インターネットアクセスとは異なります。全体がめちゃくちゃです。一部のブラウザーベンダーは、実際のネットワークアクセスが失われたときにnavigator.onLineフラグを更新しますが、そうでないものもあります。

スペックから:

ユーザーエージェントが完全にオフラインの場合(ネットワークから切断されている場合)はfalseを返します。ユーザーエージェントがオンラインである可能性がある場合はtrueを返します。

この属性の値が変更されると、オンラインとオフラインのイベントが発生します。

navigator.onLine属性は、ユーザーがリンクをたどったとき、またはスクリプトがリモートページをリクエストしたとき(またはそのような試みが失敗することがわかっているとき)にユーザーエージェントがネットワークに接続しない場合はfalseを返し、そうでない場合はtrueを返す必要があります。

最後に、仕様の注記:

この属性は本質的に信頼できません。コンピュータは、インターネットにアクセスしなくてもネットワークに接続できます。


23
接続が失われたときにChromeのみがnavigator.onLineを正しく設定します。インターネット接続を削除した場合、SafariとFirefoxはどちらもフラグをfalseに設定しません。
chovy

2
@chovyと今はどうですか?私は最近..フラグが、私はオフに設定し、され、インターネット接続にされていることを見て、Firefoxの/ Chromeでそれをテストし、期待される結果を得た
ジェームズCazzetta

12
本日2017年1月31日、OSX Chrome 55.0.2883.95、Safari 10.0.3、およびFF 50.1.0を開きました。すべてのwindow.navigator.onLineは、ネットワークに留まっているときにうまく機能しているように見えますが、ルーターからコードを外しました。それらはすべてオフラインで正しく検出されました。
nycynik 2017年

3
navigator.onLineは、すべての主要なブラウザでサポートされて(といくつかの時間のためにされている):caniuse.com/#feat=online-status
ラファエルLüder

@RafaelLüder今日の時点で正解ですが、この回答は2011年1月に書かれました。
レベッカ

34

主要なブラウザベンダーは、「オフライン」の意味が異なります。

ChromeとSafariは、ユーザーが「オフライン」になると自動的に検出します。つまり、ネットワークケーブルを外すと、「オンライン」のイベントとプロパティが自動的に起動します。

Firefox(Mozilla)、Opera、およびIEは別のアプローチを採用しており、ネットワーク接続が機能していない場合でも、ブラウザーで「オフラインモード」を明示的に選択しない限り、「オンライン」と見なします。

Firefox / Mozillaの動作には有効な引数があり、これらはこのバグレポートのコメントで概説されています。

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

しかし、質問に答えるために-オンライン/オフラインイベント/プロパティに依存して、実際にネットワーク接続があるかどうかを検出することはできません。

代わりに、代替アプローチを使用する必要があります。

このMozilla Developer記事の「Notes」セクションには、2つの代替方法へのリンクがあります。

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

「APIがブラウザーに実装されていない場合は、AppCacheエラーイベントやXMLHttpRequestからの応答のリッスンなど、他の信号を使用してオフラインかどうかを検出できます」

これは、「AppCacheエラーイベントをリッスンする」アプローチの例にリンクしています。

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

...そして「XMLHttpRequest失敗を聞く」アプローチの例:

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

HTH-チャド


1
Firefox 41以降:(updates this property when the OS reports a change in network connectivity on Windows, Linux, and OS X.あなたが言及したドキュメントによると)。あなたのブラウザの「オフラインモード」としているブラウジング場合、それはオフラインではないだけですので、

17

今日、この仕事をするオープンソースのJavaScriptライブラリがありOffline.jsます。

ユーザーにオンライン/オフライン表示を自動的に表示します。

https://github.com/HubSpot/offline

README全体を必ず確認してください。フックできるイベントが含まれています。

こちらがテストページです。それは美しいです/ところで素晴らしいフィードバックUIがあります!:)

Offline.js Simulate UIはOffline.jsプラグインであり、ブルートフォースメソッドを使用して実際の接続を無効にすることなく、ページがさまざまな接続状態にどのように応答するかをテストできます。


2
ライブラリは、実際にはローカルのファビコンを内部で繰り返しフェッチすることで機能します。私の意見では、ライブラリは大きすぎて機能が多すぎます。主なトリックは、ファビコンを繰り返しフェッチすることです。
KarelBílek16年

1
ネットワークケーブルを抜いたときにオフラインが検出されない
最高級

15

すべての主要ブラウザで現在動作する最良の方法は、次のスクリプトです。

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

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


3
コード自体のコメントには明確に記載されているように、イーサネットケーブルを取り外したり、Wi-Fiをオフにしたりすると、Firefox / Chromeでは機能しません
マニッシュ2014

「ソース」リンクと切断されたイーサネットケーブルにアクセスしてみたところ、IEでは「オフラインです」と表示されましたが、Firefox / Chromeでは表示されませんでした(すべてのブラウザーの最新バージョンを使用)。何か不足しているのでしょうか?
マニッシュ2014

13

最近から、navigator.onLineすべての主要ブラウザで同じように表示され、使用可能になっています。

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

これを正しい方法でサポートする最も古いバージョンは、Firefox 41、IE 9、Chrome 14、Safari 5です。

現在、これはユーザーのスペクトル全体を表していますが、ページのユーザーが何を持っているかを常に確認する必要があります。

FF 41以前falseは、ユーザーがブラウザーを手動でオフラインモードにした場合にのみ表示されていました。IE 8では、プロパティはではbodyなくにありましたwindow

出典:caniuse


11

window.navigator.onLine属性とそれに関連するイベントは、特定のWebブラウザ(上で現在信頼できない、特にFirefoxのデスクトップ私は定期的にネットワーク接続の状態を確認し、適切な育てること(jQueryのを使用して)少し機能を書いたので、@Juntoが言ったように)offlineonlineイベントを:

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

次のように使用できます。

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

オフラインイベントとオンラインイベントをリッスンするには(jQueryを利用):

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

7

navigator.onLineはごちゃごちゃです

サーバーにajax呼び出しを行おうとすると、これに直面します。

クライアントがオフラインの場合、いくつかの状況が考えられます。

  • ajax呼び出しがタイムアウトになり、エラーが発生する
  • ajax呼び出しは成功を返しますが、メッセージはnullです
  • ブラウザが決定するため、ajax呼び出しは実行されません(しばらくするとnavigator.onLineがfalseになる場合があります)

私が使用している解決策は、javascriptを使用して自分でステータスを制御することです。成功した呼び出しの条件を設定しました。それ以外の場合は、クライアントがオフラインであると想定します。このようなもの:

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

5

HTML5では、navigator.onLineプロパティを使用できます。ここを見て:

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

Javascriptが「ブラウザ」変数を準備するだけで、オフラインかオンラインかを認識しているため、現在の動作はおそらくランダムですが、実際にはネットワーク接続はチェックされません。

これがあなたが探しているものかどうかをお知らせください。

敬具、


あなたの助けをありがとうTrefex。コードを変更し、navigator.onLineプロパティのみを確認しましたが、以前と同じ動作になります。mattbastaのコメントをご覧ください。
Pierre Duplouy、2010

こんにちはペドロ、私はmattbastaに同意しますが、それがあなたのために機能することを望みました:)私は間違いなくAjaxメソッドを使用して、常に稼働していることがわかっているURLをクエリし、接続が失われたかどうかを確認します。別の注意として、なぜオンライン/オフラインの状態を正確に検出する必要があるのですか?多分私達がもっと知っていれば、あなたの問題のための別の解決策があるでしょう。お知らせください
Trefex

1
わかりました、ありがとう:)アプリケーションが接続の変更を自動検出できれば、ユーザーにとってより良いと思いました(FFまたはIEでオフラインモードを手動で有効にする必要はありません)。このようにして、アプリケーションがオフラインになると、サーバーにクエリを実行する代わりにローカルキャッシュを使用します。John Resigからこの投稿が見つかりました。これがうまくいかない理由をかなり説明しています:ejohn.org/blog/offline-events
Pierre Duplouy 2010

ブログ投稿ありがとうございます。Rellyの詳細な分析と要点。私はあなたがいくつかのサーバー(たぶんあなた自身のもの)をクエリし、x回のタイムアウトがあるときにローカルキャッシュに切り替えるのが一番いいと思います。どう思いますか ?
Trefex 2010

ええ、私はそれが最良の選択肢だと思います-現在の最先端技術を考えると。最終的にすべてのブラウザが実際の接続の喪失を自分で検出できることを願っています。navigator.onLineの使用は非常に単純で、これはそれほど複雑ではないはずです。思いませんか?
Pierre Duplouy、2010

3

オフライン用に作成したrequire.jsモジュールを見つけてください。

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

このブログ投稿を読んで、あなたの考えを教えてください。http://zen-and-art-of-programming.blogspot.com/2014/04/html-5-offline-application-development.htmlこれには、offline.jsを使用してクライアントがオフラインであることを検出するコードサンプルが含まれています。


3
リンクのみの回答は推奨されないことに注意してください。SOの回答は、ソリューションの検索のエンドポイントである必要があります。参照としてリンクを維持しながら、ここにスタンドアロンの概要を追加することを検討してください。
クレオパトラ2014

こんにちは、リンク参照とともにrequire.jsモジュールを投稿しました。提案をありがとう。
Srihari Sridharan 2014年

2

あなたは以下のように簡単にオフラインのクロスブラウザの方法を検出することができます

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

yoururl.comをに置き換えることができますdocument.location.pathname

解決策の核心は、接続できない場合はドメイン名に接続してみることです-あなたはオフラインです。クロスブラウザで動作します。


ドメイン名の後にURL名がないため、404を取得する変更はありません
harishr

ときどき、私のAPIのホームページが404であるように
Ben Aubin 2015

APIのホームページはどのように重要ですか?理解できませんでした。サーバーにヒットしたときにURLがないため、ホームページが404であっても処理されないため、問題ありません。あなたが言っている問題を私が試して理解できるいくつかのサンプルコードを提供できるかどうかかもしれません
harishr

私のAPIだけでなく、多くのサイトにはホームページがありません。受信したステータスコードとデータがnullであることを確認します。これが、通常の予期されるエラーではないことを確認する最良の方法です
Ben Aubin

私のwebapiにもホームページはありませんが、上記はまだ機能します。それが私が混乱している理由です。ホームページが機能していることを考えると、ホームページはどのように重要なのか
harishr

2

HTML5キャッシュマニフェストのFALLBACKオプションを使用して、次の方法でhtml5アプリがオンラインかオフラインかを確認します。

FALLBACK:
/online.txt /offline.txt

HTMLページでjavascriptを使用して、オンライン/オフラインのtxtファイルの内容を読み取ります。

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

オフラインになると、スクリプトはoffline.txtの内容を読み取ります。ファイル内のテキストに基づいて、Webページがオンラインかオフラインかを検出できます。


0

これが私の解決策です。

IE、Opera、Chrome、FireFox、Safariで、IOS 8のPhonegap WebAppおよびAndroid 4.4.2のPhonegap WebAppとしてテスト済み

このソリューションは、localhost上のFireFoxでは機能しません。

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

onlineCheck.js(ファイルパス: "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(ファイルパス: "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(ファイルパス: "root"):

<?php echo 'true'; ?> 


0

ドキュメント本文の使用:

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

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

});

参照
Document-Body:ononline Event
Javascript-Event:Online and offline events

追加の考え:
「ネットワーク接続はインターネット接続と同じではありません」を回避するには、上記の方法の問題:アプリケーションの起動時にajaxを使用してインターネット接続を一度確認し、オンライン/オフラインモードを構成できます。ユーザーがオンラインになるための再接続ボタンを作成します。失敗した各ajaxリクエストに、ユーザーをオフラインモードに戻す機能を追加します。


1
これは機能しませんwindow.addEventListener('online', updateOnlineStatus(event) );。updateOnlineStatus()関数をすぐに呼び出しているためです。それはする必要がありますwindow.addEventListener('online', updateOnlineStatus );
セバスチャン・Rosset
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.