Как определить кроссбраузерность онлайн/оффлайн событий?

Я пытаюсь точно определить, когда браузер отключается, используя онлайн- и офлайн-события 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 с тайм-аутами.


person Pierre Duplouy    schedule 05.07.2010    source источник
comment
Я согласен с Trefex, но я также хотел бы добавить, что поддержка обнаружения соединения в лучшем случае некачественная для большинства приложений: только потому, что провод отключен, это не означает немедленной потери соединения. Использование метода, который физически не проверяет, открыто ли соединение, не может гарантировать точные результаты.   -  person mattbasta    schedule 06.07.2010
comment
Спасибо за совет. Итак, вы бы порекомендовали метод Ajax? т.е. продолжать отправлять вызовы XHR с таймаутами?   -  person Pierre Duplouy    schedule 06.07.2010
comment
Реализация Firefox (а также IE и Opera) неверна. См. мой комментарий по этому поводу здесь: bugzilla.mozilla.org/show_bug.cgi? id=654579#c9   -  person thewoolleyman    schedule 11.03.2012
comment
Вы можете проверить Offline.js, библиотеку с открытым исходным кодом, созданную именно для этой цели.   -  person Adam    schedule 28.10.2013


Ответы (14)


В настоящее время в 2011 году различные поставщики браузеров не могут договориться о том, как определить автономный режим. В некоторых браузерах есть функция «Работать автономно», которую они считают отдельной от отсутствия доступа к сети, что опять же отличается от доступа в Интернет. Все дело в беспорядке. Некоторые поставщики браузеров обновляют флаг navigator.onLine при потере фактического доступа к сети, другие — нет.

Из спецификации:

Возвращает false, если пользовательский агент определенно находится в автономном режиме (отключен от сети). Возвращает true, если пользовательский агент может быть в сети.

События онлайн и офлайн запускаются при изменении значения этого атрибута.

Атрибут navigator.onLine должен возвращать false, если пользовательский агент не будет связываться с сетью, когда пользователь переходит по ссылкам или когда скрипт запрашивает удаленную страницу (или знает, что такая попытка не удастся), в противном случае должен возвращать true.

Наконец, спецификация отмечает:

Этот атрибут по своей сути ненадежен. Компьютер может быть подключен к сети без доступа в Интернет.

person Rebecca    schedule 27.01.2011
comment
Только Chrome правильно устанавливает navigator.onLine при потере подключения. И Safari, и Firefox никогда не устанавливают флаг в false, если вы удаляете подключение к Интернету. - person chovy; 04.10.2011
comment
@chovy а как насчет сейчас? Недавно я протестировал его в Firefox/Chrome и получил ожидаемые результаты, увидев, что флаг устанавливается, когда я выключаю и подключаю интернет-соединение. - person James Cazzetta; 27.11.2015
comment
Сегодня, 31 января 2017 г., я открыл OSX Chrome 55.0.2883.95, Safari 10.0.3 и FF 50.1.0. Весь window.navigator.onLine, похоже, отлично работает, когда я оставался в своей сети, но отключил шнур от маршрутизатора. Все они корректно определяются в автономном режиме. - person nycynik; 31.01.2017
comment
navigator.onLine поддерживается всеми основными браузерами (и поддерживается уже некоторое время): caniuse.com/# feat=онлайн-статус - person rlueder; 30.03.2018
comment
@RafaelLüder Верно на сегодняшний день, но этот ответ был написан в январе 2011 года! - person Rebecca; 03.04.2018
comment
Если вы используете Reactjs, вы можете использовать пакет npm react-detect-offline. - person Shubham Chopra; 07.03.2019
comment
@ShubhamChopra Этому ответу 8 лет :) - person Rebecca; 07.03.2019
comment
Да, именно поэтому я обновил для тех, кто пытается понять, как это сделать в 2019 году, поскольку offline.js сейчас активно не поддерживается. - person Shubham Chopra; 07.03.2019
comment
Также обратите внимание, что это может варьироваться в зависимости от устройства, поэтому автономный режим на Android работает лучше, чем, например, на Windows. - person PeterS; 07.02.2020
comment
См. также: navigator.onLine не всегда работает - person mic; 15.09.2020

Основные поставщики браузеров расходятся во мнениях относительно того, что означает автономный режим.

Chrome, Safari и Firefox (начиная с версии 41) автоматически определяют, когда вы выходите из сети, а это означает, что онлайн-события и свойства запускаются автоматически, когда вы отключаете сетевой кабель.

Mozilla Firefox (до версии 41), Opera и IE используют другой подход и считают, что вы подключены к сети, если вы явно не выберете автономный режим в браузере, даже если у вас нет рабочего сетевого подключения.

Существуют веские аргументы в пользу поведения Firefox/Mozilla, которые изложены в комментариях к этому отчету об ошибке:

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

Но, чтобы ответить на вопрос, вы не можете полагаться на события/свойство онлайн/офлайн, чтобы определить, действительно ли существует сетевое подключение.

Вместо этого вы должны использовать альтернативные подходы.

Раздел «Примечания» этой статьи для разработчиков Mozilla содержит ссылки на два альтернативных метода:

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, -- Чад

person thewoolleyman    schedule 13.03.2012
comment
Начиная с Firefox 41: updates this property when the OS reports a change in network connectivity on Windows, Linux, and OS X. (согласно документам, которые вы упомянули). Так что это не только в автономном режиме, если вы просматриваете браузер в автономном режиме - person dude; 20.01.2017

Сегодня существует библиотека JavaScript с открытым исходным кодом, которая выполняет эту работу: она называется Offline.js.

Автоматически отображать индикацию онлайн/офлайн для ваших пользователей.

https://github.com/HubSpot/offline

Обязательно ознакомьтесь с полным README. Он содержит события, к которым вы можете подключиться.

Вот тестовая страница. Кстати, это красиво / имеет приятный интерфейс обратной связи! :)

Offline.js Simulate UI — это подключаемый модуль Offline.js, который позволяет вам проверить, как ваши страницы реагируют на различные состояния подключения, без необходимости использовать методы грубой силы для отключения фактического подключения.

person Leniel Maccaferri    schedule 28.05.2014
comment
Библиотека на самом деле работает, многократно извлекая локальный значок из-под капота. На мой взгляд, библиотека слишком большая и имеет слишком много функций; главный трюк — это просто повторное получение значка. - person Karel Bílek; 10.10.2016
comment
Не обнаруживает автономный режим, когда я отключаю сетевой кабель - person poshest; 26.07.2019

Лучший способ, который сейчас работает во всех основных браузерах, — это следующий скрипт:

(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

person tmaximini    schedule 23.08.2013
comment
Как ясно указано в комментариях к самому коду, он не работает в Firefox/Chrome, если вы отключите кабель Ethernet или отключите Wi-Fi. - person Manish; 21.02.2014
comment
Я попытался перейти по ссылке «Источник» и отсоединить кабель Ethernet, он показал, что вы не в сети в IE, но не в Firefox/Chrome для меня (используя последнюю версию всех браузеров). Может я что-то упускаю? - person Manish; 24.02.2014

С недавнего времени 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

person Haroen Viaene    schedule 01.04.2016

Примечание от 23 июня 2021 г.

Как вы можете видеть в Могу ли я использовать, встроенная поддержка этой функции значительно улучшилась за последние годы, так как основные ошибки были устранены. Хакерские вещи ниже больше не нужны.


Атрибут window.navigator.onLine и связанные с ним события в настоящее время ненадежны. в некоторых веб-браузерах (особенно Firefox для настольных компьютеров), как сказал @Junto, поэтому я написал немного функция (использующая jQuery), которая периодически проверяет состояние подключения к сети и вызывает соответствующий offline и события online:

// Global variable somewhere in your app to replicate the 
// window.navigator.onLine variable (this last 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');
  }
});
person Epoc    schedule 17.02.2015

navigator.onLine - беспорядок

Я сталкиваюсь с этим при попытке сделать ajax-вызов на сервер.

Возможны несколько ситуаций, когда клиент не в сети:

  • тайм-ауты вызова ajax, и вы получаете сообщение об ошибке
  • вызов ajax возвращает успех, но сообщение равно null
  • вызов ajax не выполняется, потому что так решил браузер (может быть, это когда navigator.onLine через некоторое время становится ложным)

Решение, которое я использую, состоит в том, чтобы самостоятельно контролировать статус с помощью 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);
          }
        });
      }
person Toolkit    schedule 22.06.2011

В HTML5 вы можете использовать свойство navigator.onLine. Смотри сюда:

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

Вероятно, ваше текущее поведение является случайным, поскольку javascript только готовит переменную «браузер», а затем знает, находитесь ли вы в автономном режиме и в сети, но на самом деле он не проверяет сетевое подключение.

Дайте нам знать, если это то, что вы ищете.

С уважением,

person Trefex    schedule 05.07.2010
comment
Спасибо за вашу помощь Трефекс. Я изменил свой код и теперь проверяю только свойство navigator.onLine, однако получаю то же поведение, что и раньше. Пожалуйста, взгляните на комментарий mattbasta. - person Pierre Duplouy; 06.07.2010
comment
Привет, Педро, я согласен с mattbasta, но я надеялся, что это сработает для вас :) Я бы определенно использовал метод Ajax для запроса некоторого URL-адреса, который, как вы знаете, всегда активен, и тогда вы бы знали, потеряно ли соединение или нет. С другой стороны, почему вам требуется точное определение статуса онлайн / офлайн? Возможно, если бы мы знали больше, нашлось бы другое решение вашей проблемы. Дайте нам знать, - person Trefex; 06.07.2010
comment
Спасибо за этот пост в блоге. Надейтесь на глубокий анализ и прямо в точку. Я думаю, чего вы хотите достичь, лучше всего, если вы запросите какой-либо сервер (возможно, свой собственный), а затем переключитесь на локальный кеш, когда будет x количество тайм-аутов. Что вы думаете ? - person Trefex; 06.07.2010
comment
Да, я думаю, это лучший вариант, учитывая нынешнее состояние дел. Я надеюсь, что со временем все браузеры смогут самостоятельно обнаруживать фактическую потерю соединения: использование navigator.onLine довольно просто, и это не должно быть более сложным. Вам не кажется? - person Pierre Duplouy; 06.07.2010
comment
Chrome — единственный браузер, который обновляет navigator.onLine при потере связи. - person chovy; 04.10.2011

Пожалуйста, найдите модуль require.js, который я написал для 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;
});

Пожалуйста, прочитайте этот пост в блоге и дайте мне знать ваши мысли. http://zen-and-art-of-programming.blogspot.com/2014/04/html-5-offline-application-development.html Он содержит пример кода, использующий offline.js для определения, когда клиент находится в автономном режиме.

person Srihari Sridharan    schedule 15.04.2014

вы можете легко обнаружить автономный кросс-браузерный способ, как показано ниже

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.

Суть решения в том, что попробуйте подключиться к вашему доменному имени, если вы не можете подключиться - вы не в сети. работает кроссбраузерно.

person harishr    schedule 22.04.2015
comment
Иногда нет, например, домашняя страница моего API — 404. - person Ben Aubin; 26.04.2015
comment
Не только мой API, но и многие сайты не имеют домашней страницы. Убедитесь, что код состояния и полученные данные равны нулю, это лучший способ убедиться, что это не просто нормальная ожидаемая ошибка. - person Ben Aubin; 26.04.2015
comment
@ penne12 Я использовал этот ответ, и он также работает в моем веб-API. - person algos; 26.04.2015
comment
Это работает, но имеет неожиданные последствия, как я объяснил (ошибка означает ошибку или ошибку не в 200, иногда сервер тоже будет отключен) - person Ben Aubin; 26.04.2015
comment
если сервер не работает, то мы не в сети, это то, что мы пытаемся обнаружить здесь, правильно - person harishr; 27.04.2015
comment
Работает как шарм, response.status == 0, если он не может подключиться к хосту, возвращается статус 0. - person Niels; 28.09.2015
comment
Мех. Это нормально. Вопрос был конкретно о событии. Однократная проверка или периодический опрос работают, но это определенно не то же самое, что работа с событиями. - person rinogo; 20.01.2017

Я использую параметр FALLBACK в манифесте кеша HTML5, чтобы проверить, находится ли мое приложение html5 в сети или в автономном режиме:

FALLBACK:
/online.txt /offline.txt

На html-странице я использую javascript для чтения содержимого онлайн/оффлайн файла txt:

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

В автономном режиме скрипт будет читать содержимое файла offline.txt. На основе текста в файлах вы можете определить, находится ли веб-страница в сети или в автономном режиме.

person Marcel Scholte    schedule 08.03.2016

Вот мое решение.

Протестировано с IE, Opera, Chrome, FireFox, Safari, как веб-приложение Phonegap на IOS 8 и как веб-приложение Phonegap на Android 4.4.2

Это решение не работает с 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'; ?> 
person JoJoWhatsUp    schedule 30.09.2014

ну, вы можете попробовать плагин javascript, который может отслеживать соединение браузера в режиме реального времени и уведомляет пользователя, если Интернет или соединение браузера с Интернетом прервалось.

плагин Wiremonkey Javascript и демо можно найти здесь

http://ryvan-js.github.io/

person Ry Van    schedule 29.06.2016

Использование тела документа:

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

});

Ссылка:
Основная часть документа: онлайн-мероприятие
Javascript-Event: Онлайн- и офлайн-события

Дополнительные мысли:
Чтобы обойти "сетевое соединение не то же самое, что подключение к Интернету" Проблема из приведенных выше методов: вы можете проверить подключение к Интернету один раз с помощью ajax при запуске приложения и настроить онлайн/оффлайн режим. Создайте кнопку повторного подключения, чтобы пользователь мог выйти в сеть. И добавьте к каждому неудачному ajax-запросу функцию, которая возвращает пользователя в автономный режим.

person Milingu Kilu    schedule 25.01.2017
comment
Это не сработает: window.addEventListener('online', updateOnlineStatus(event) ); потому что вы немедленно вызываете функцию updateOnlineStatus(). Должно быть window.addEventListener('online', updateOnlineStatus ); - person Sébastien Rosset; 27.02.2018