Як виявити перехресний браузер події в режимі онлайн / офлайн?


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 з таймаутами?
П’єр Дуплой

Реалізація Firefox (а також IE і Opera) неправильна. Дивіться мій коментар до цього ефекту тут: bugzilla.mozilla.org/show_bug.cgi?id=654579#c9
thewoolleyman

4
Ви можете перевірити Offline.js , бібліотеку з відкритим кодом, побудовану саме для цієї мети.
Адам

Відповіді:


70

Постачальники веб-переглядачів не можуть домовитися про те, як визначити офлайн. Деякі браузери мають функцію Work Offline, яку вони вважають окремою через відсутність доступу до мережі, що знову ж таки відрізняється від доступу до Інтернету. Вся справа - безлад. Деякі постачальники браузерів оновлюють прапор navigator.onLine, коли фактичний доступ до мережі втрачається, інші - ні.

З специфікації:

Повертає помилку, якщо агент користувача точно не в мережі (відключений від мережі). Повертає істину, якщо агент користувача може бути в мережі.

Події в Інтернеті та офлайн запускаються, коли значення цього атрибуту змінюється.

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

Нарешті, специфікація зазначає:

Цей атрибут по суті є ненадійним. Комп'ютер можна підключити до мережі, не маючи доступу до Інтернету.


23
Тільки Chrome правильно встановлює navigator.onLine, коли втрачається зв’язок. І Safari, і Firefox ніколи не встановлюють прапор значення false, якщо ви вилучите Інтернет-з'єднання.
chovy

2
@chovy, а як же тепер? Нещодавно я перевірив його у Firefox / Chrome і отримав очікувані результати, побачивши, що прапор встановлюється, коли я
вимикаюсь

12
Сьогодні 31.01.2017 я відкрив OSX Chrome 55.0.2883.95, Safari 10.0.3 та FF 50.1.0. Здається, що всі window.navigator.onLine чудово спрацювали, коли я залишився в мережі, але вийняв шнур з маршрутизатора. Всі вони правильно виявлені в режимі офлайн.
nycynik

3
navigator.onLine підтримується у всіх основних браузерах (і є вже деякий час): caniuse.com/#feat=online-status
Рафаель Людер

@ RafaelLüder Правильна станом на сьогодні, але ця відповідь була написана в січні 2011 року!
Ребекка

34

Основні постачальники браузерів відрізняються тим, що означає "офлайн".

Chrome і Safari виявлять, коли ви переходите в режим "офлайн" автоматично - це означає, що події та властивості "в Інтернеті" запускаються автоматично при відключенні мережного кабелю.

Firefox (Mozilla), Opera та IE застосовують інший підхід і вважають вас "он-лайн", якщо ви чітко не вибрали "Офлайн-режим" у браузері - навіть якщо у вас немає підключення до мережі.

Існують вагомі аргументи для поведінки Firefox / Mozilla, які викладені в коментарях до цього звіту про помилки:

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

Але, щоб відповісти на запитання, ви не можете розраховувати на події / властивості в Інтернеті / офлайн, щоб виявити, чи є насправді мережевий зв’язок.

Натомість потрібно використовувати альтернативні підходи.

Розділ "Примітки" цієї статті розробника Mozilla містить посилання на два альтернативних способи:

https://developer.mozilla.org/uk/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 . Він містить події, які можна підключити.

Ось тестова сторінка . Це красиво / має приємний інтерфейс відгуків, до речі! :)

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


2
Бібліотека фактично працює, отримуючи місцевий фавікон кілька разів під кришкою. На мою думку, бібліотека занадто "велика" і має занадто багато функцій; головна хитрість - це просто отримання фавікону кілька разів.
Карел Білек

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
Як видно із зауважень у самому коді - він не працює у Firefox / Chrome, якщо ви відключите кабель Ethernet або відключите Wi-Fi.
Маніш

Я спробував завітати на посилання "Джерело" та відключив кабель Ethernet, він показав "Ви в автономному режимі" в IE, але не в Firefox / Chrome для мене (використовуючи останню версію всіх браузерів). Може, я щось пропускаю?
Маніш

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.

джерело: канюза


11

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

// 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 повертає успіх, але повідомлення недійсне
  • виклик ajax не виконується, тому що браузер вирішує так (можливо, коли навігатор.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);
          }
        });
      }

5

У HTML5 ви можете використовувати navigator.onLineвластивість. Послухайте:

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

Можливо, ваша поточна поведінка є випадковою, оскільки javascript готовий лише до змінної "браузер", а потім знає, чи ви в автономному режимі та в Інтернеті, але це насправді не перевіряє мережеве з'єднання.

Повідомте нас, якщо це те, що ви шукаєте.

З повагою,


Дякуємо за вашу допомогу Trefex. Я змінив свій код і тепер перевіряю лише властивість navigator.onLine, проте я отримую таку ж поведінку, як і раніше. Будь ласка, подивіться на коментар mattbasta.
П’єр Дюпло

Привіт Педро, я погоджуюся з mattbasta, але я сподівався, що це буде працювати для вас :) Я б точно використав метод Ajax для запиту URL-адреси, про яку ви знаєте, що завжди працює, і тоді ви знатимете, втрачено чи ні. З іншого приводу, чому вам потрібно точно визначити статус в режимі онлайн / офлайн? Можливо, якби ми дізналися більше, було б ще одне рішення для вашої проблеми. Повідомте нас,
Trefex

1
Гаразд, дякую :) Я просто подумав, що користувачеві буде краще, якщо програма зможе автоматично виявити зміну підключення (не потрібно вручну вмикати офлайн-режим у FF або IE). Таким чином, коли програма перейде в автономний режим, вона використовуватиме свій локальний кеш, а не запитувати сервер. Я знайшов цю публікацію від Джона Ресіга, яка в значній мірі
Pierre Duplouy

Дякую за цю публікацію в блозі. Повторимося в глибинному аналізі та право на точку. Я думаю, що найкраще, якщо ви хочете отримати запит на якийсь сервер (можливо, власний), а потім перейти до локального кешу, коли є х кількість очікувань. Що ти думаєш ?
Trefex

Так, я думаю, що це найкращий варіант - враховуючи сучасний стан техніки. Я сподіваюся, що з часом усі браузери зможуть виявити фактичну втрату зв’язку самостійно: користуватися navigator.onLine досить просто, і це не повинно бути складніше. Ти не думаєш?
П’єр Дуплой

3

Знайдіть модуль Requ.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 повинні бути кінцевою точкою пошуку рішення (проти ще однієї зупинки посилань, яка, як правило, затягується з часом). Будь ласка, розглянути можливість додавання сюди окремого конспекту, зберігаючи посилання як орієнтир.
Клеопатра

Привіт, я розмістив модуль Requ.js разом із посиланням на посилання. Дякую за пропозицію.
Шріхарі Шрідхаран

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, зміни 40 для отримання 404
harishr

Іноді ні, як домашня сторінка мого апі - це 404
Бен Аубін

як важлива домашня сторінка Апі ?? не зрозумів. адже коли він потрапляє на сервер, немає URL-адреси - тому ніякої обробки, навіть якщо ваша домашня сторінка 404 - це не має значення. можливо, якщо ви можете надати зразок коду, який я можу спробувати зрозуміти проблему, яку ви заявляєте
harishr

Не тільки мої api, але багато сайтів не мають домашньої сторінки. Переконайтеся, що код статусу та отримані дані є недійсними, це найкращий спосіб переконатися, що це не просто звичайна, очікувана помилка
Бен Аубін

у мого веб-сайту також немає домашньої сторінки, але вищезазначене все ще працює. ось чому я розгублений. як важлива домашня сторінка, враховуючи, що її робота
harishr

2

Я використовую опцію FALLBACK в маніфесті кешу HTML5, щоб перевірити, чи є моя програма html5 в Інтернеті чи офлайн:

FALLBACK:
/online.txt /offline.txt

На html-сторінці я використовую javascript tot, щоб прочитати вміст txt-файлу онлайн / офлайн:

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

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


0

Ось моє рішення.

Тестовано на IE, Opera, Chrome, FireFox, Safari, як Phonegap WebApp на IOS 8 та як Phonegap WebApp на Android 4.4.2

Це рішення не працює з FireFox на localhost.

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

onlineCheck.js (filepath: "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 (filepath: "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 (filepath: "root"):

<?php echo 'true'; ?> 

0

добре, ви можете спробувати плагін JavaScript, який може відслідковувати з'єднання браузера в режимі реального часу та сповіщати користувача, якщо зв’язок Інтернету чи браузерів з Інтернетом знизився.

Плагін Wiremonkey Javascript та демо-версію, яку ви можете знайти тут

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


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

});

Довідково :
Документ-орган: on-line подія
Javascript-подія: події в Інтернеті та в режимі офлайн

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


1
Це не спрацює, window.addEventListener('online', updateOnlineStatus(event) );оскільки ви негайно викликаєте функцію updateOnlineStatus (). Це повинно бутиwindow.addEventListener('online', updateOnlineStatus );
Себастьян Россет
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.