Обнаружить интернет-соединение в автономном режиме?

246

Как обнаружить интернет-соединение в автономном режиме в JavaScript?

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

Ответы:

135

Вы можете определить, что соединение потеряно, выполнив неудачные запросы XHR .

Стандартный подход - повторить запрос несколько раз. Если этого не произойдет, предупредите пользователя, чтобы он проверил соединение, и завершите с ошибкой .

Sidenote: перевод всего приложения в автономное состояние может привести к большой подверженности ошибкам работе по обработке состояния. Беспроводные соединения могут приходить и уходить и т. Д. Поэтому лучше всего просто изящно завершить работу, сохранить данные, и предупредить пользователя .. позволяя им в конечном итоге решить проблему с подключением, если таковая имеется, и продолжать использовать ваше приложение с достаточным количеством прощения.

Примечание. Вы можете проверить наличие надежного сайта, такого как Google, на предмет подключения, но это может быть не совсем полезным, поскольку вы просто пытаетесь сделать свой собственный запрос, потому что, хотя Google может быть доступен, ваше собственное приложение может и не быть, и вы все равно будете приходится решать ваши собственные проблемы с подключением. Попытка отправить пинг в Google была бы хорошим способом подтвердить, что интернет-соединение отключено, поэтому, если эта информация вам полезна, то это может стоить хлопот.

Замечание . Отправка Ping может быть осуществлена ​​так же, как если бы вы делали двусторонний Ajax-запрос любого типа, но отправка Ping в Google в этом случае создаст некоторые проблемы. Во-первых, у нас будут те же междоменные проблемы, которые обычно возникают при создании Ajax-коммуникаций. Один из вариантов - настроить прокси на стороне сервера, в котором мы на самом деле pingGoogle (или любой другой сайт), и вернуть результаты пинга в приложение. Это уловка-22потому что если проблема связана с интернет-соединением, мы не сможем добраться до сервера, и если проблема с подключением будет только в нашем собственном домене, мы не сможем заметить разницу. Можно попробовать другие междоменные методы, например, встроить на свою страницу iframe, который указывает на google.com, а затем опросить iframe на предмет успеха / неудачи (проверить содержимое и т. Д.). Встраивание изображения может ничего не сказать нам, потому что нам нужен полезный ответ от коммуникационного механизма, чтобы сделать хороший вывод о том, что происходит. Итак, еще раз, определение состояния интернет-соединения в целом может быть больше проблем, чем оно того стоит. Вам придется взвесить эти опции для вашего конкретного приложения.

keparo
источник
84
Повторное «Sidenote» звучит как Дуайт Шруте, говорящий «Вопрос ...» :-)
Брайан Келли
19
Почему «catch-22» выделено жирным шрифтом?
codingbear
33
Теперь в 2012 году вы можете проверить переменную navigator.onLine;)
João Pinto Jerónimo
13
navigator.online/offline также ненадежен по тем же причинам. См stackoverflow.com/questions/3181080/...
Efran Cobisi
17
Вы можете проверить Offline.js , библиотеку с открытым исходным кодом , созданную именно для этой цели.
Адам
51

IE 8 будет поддерживать свойство window.navigator.onLine .

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

Пока этого не произойдет, либо XHR, либо запрос Image()или <img>могут предоставить что-то близкое к желаемой функциональности.

Обновление (2014/11/16)

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

Цитата из документации Mozilla :

В Chrome и Safari, если браузер не может подключиться к локальной сети (LAN) или маршрутизатору, он находится в автономном режиме; все остальные условия возвращаются true. Таким образом, хотя вы можете предполагать, что браузер находится в автономном режиме, когда он возвращает falseзначение, вы не можете предполагать, что истинное значение обязательно означает, что браузер может получить доступ к Интернету. Вы можете получить ложные срабатывания, например, в тех случаях, когда на компьютере запущено программное обеспечение для виртуализации с виртуальными адаптерами Ethernet, которые всегда «подключены». Поэтому, если вы действительно хотите определить онлайн-статус браузера, вам следует разработать дополнительные средства для проверки.

В Firefox и Internet Explorer переключение браузера в автономный режим отправляет falseзначение. Все остальные условия возвращают trueзначение.

Грант Вагнер
источник
5
navigator.onLine является частью HTML5 - другие браузеры уже имеют версии для разработки, которые предоставляют его - он уже доступен в Firefox 3 сегодня.
olliej
- но, к сожалению, недоступно в более ранних версиях IE, которые мы часто должны поддерживать.
Кепаро
22
navigator.onLine показывает состояние браузера, а не фактическое соединение. Таким образом, вы можете настроить свой браузер на OnLine, но на самом деле он не будет работать, потому что соединение не работает. navigator.onLine будет иметь значение false, только если браузер настроен на автономный просмотр.
5
если я выключу WI-FI на моем Nexus7, страница все равно скажет, что navigator.onLine равен TRUE. Плохо ...
Walv
42

Почти все основные браузеры теперь поддерживают window.navigator.onLineсвойство, а также соответствующие события onlineи offlineокна:

window.addEventListener('online', () => console.log('came online'));
window.addEventListener('offline', () => console.log('came offline'));

Попробуйте настроить систему или браузер в автономном / онлайн-режиме и проверьте консоль или window.navigator.onLineсвойство на предмет изменения значений. Вы также можете проверить это на этом сайте .

Обратите внимание на эту цитату из документации Mozilla :

В Chrome и Safari, если браузер не может подключиться к локальной сети (LAN) или маршрутизатору, он находится в автономном режиме; все остальные условия возвращаются true. Таким образом, хотя вы можете предполагать, что браузер находится в автономном режиме, когда он возвращает falseзначение , вы не можете предполагать, что trueзначение обязательно означает, что браузер может получить доступ к Интернету . Вы можете получить ложные срабатывания, например, в тех случаях, когда на компьютере запущено программное обеспечение для виртуализации с виртуальными адаптерами Ethernet, которые всегда «подключены». Поэтому, если вы действительно хотите определить онлайн-статус браузера, вам следует разработать дополнительные средства для проверки.

В Firefox и Internet Explorer переключение браузера в автономный режим отправляет falseзначение. До Firefox 41 все остальные условия возвращают trueзначение; начиная с Firefox 41 в OS X и Windows, значение будет соответствовать фактическому сетевому подключению.

(акцент мой)

Это означает, что если window.navigator.onLineесть false(или вы получаете offlineсобытие), вы гарантированно не будете иметь подключения к Интернету.

Однако, если это так true(или вы получаете onlineсобытие), это означает, что система в лучшем случае только подключена к какой-либо сети. Это не значит, что у вас есть доступ к интернету например. Чтобы проверить это, вам все равно нужно будет использовать одно из решений, описанных в других ответах.

Первоначально я намеревался опубликовать это как обновление к ответу Гранта Вагнера , но это казалось слишком большой правкой, особенно учитывая, что обновление 2014 года уже не от него .

Дидье Л
источник
Лучший ответ. Спасибо.
vibs2006
1
Недавно у меня была возможность немного поработать над поведением в автономном режиме. Мероприятия прекрасно использовать, НО ios safari создаст проблемы. Когда вы включаете Интернет на своем телефоне, автономные / онлайн-события будут задерживаться на 2 секунды, что может быть проблематично из-за визуальной визуализации, поскольку вы не можете предсказать будущее. Это просто то, что я хотел упомянуть и может кому-то помочь.
TeeJaay
38

Есть несколько способов сделать это:

  • Запрос AJAX на ваш собственный сайт. Если этот запрос не выполняется, есть большая вероятность, что это ошибка соединения. В документации JQuery есть раздел по обработке неудачных запросов AJAX . При этом остерегайтесь той же политики происхождения , которая может помешать вам получить доступ к сайтам за пределами вашего домена.
  • Вы можете положить onerrorв img, как

    <img src='http://www.example.com/singlepixel.gif' 
          onerror='alert("Connection dead");' />

    Этот метод может также потерпеть неудачу, если исходное изображение будет перемещено / переименовано, и, как правило, будет худшим выбором для опции ajax.

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

ConroyP
источник
36
 if(navigator.onLine){
  alert('online');
 } else {
  alert('offline');
 }
Edmhs
источник
11
Всегда возвращает TRUE, если в браузере.
Славчо
2
Ну, во-первых, я пытался отключить ТОЛЬКО ЛВС, но он всегда возвращал ИСТИНА. Поэтому, когда я отключил все сети (LAN2, Virtual Box и т. Д.), Он вернул FALSE.
Славчо
3
Этот ответ дублирует несколько существующих ответов за 3 года до этого.
JasonMArcher
2
он не проверяет интернет-соединение, он проверяет только
сетевое
Работал для меня в HTML 5, JavaScript, в MacBook (используя Wi-Fi), даже работал в мобильном телефоне. но проблема в том, когда Wi-Fi на нем возвращается ИСТИНА каждый раз, даже если я выключаю Wi-Fi наоборот.
С.Ядав
11

API-интерфейс кэша приложения HTML5 определяет navigator.onLine, который в настоящее время доступен в бета-версиях IE8, ночных WebKit (например, Safari) и уже поддерживается в Firefox 3.

olliej
источник
11

Вы можете использовать $ .ajax () «s errorобратного вызова, который срабатывает , если запрос не удается. Если textStatusравно строке "timeout", это, вероятно, означает, что соединение разорвано:

function (XMLHttpRequest, textStatus, errorThrown) {
  // typically only one of textStatus or errorThrown 
  // will have info
  this; // the options for this ajax request
}

Из документа :

Ошибка : функция, вызываемая в случае сбоя запроса. Функции передается три аргумента: объект XMLHttpRequest, строка, описывающая тип возникшей ошибки и необязательный объект исключения, если таковой произошел. Возможные значения для второго аргумента (кроме нуля): «timeout», «error», «notmodified» и «parsererror». Это событие Ajax

Так, например:

 $.ajax({
   type: "GET",
   url: "keepalive.php",
   success: function(msg){
     alert("Connection active!")
   },
   error: function(XMLHttpRequest, textStatus, errorThrown) {
       if(textStatus == 'timeout') {
           alert('Connection seems dead!');
       }
   }
 });
karim79
источник
9

Как сказал olliej, использование navigator.onLineсвойства браузера предпочтительнее, чем отправка сетевых запросов, и, соответственно с developer.mozilla.org/En/Online_and_offline_events , оно даже поддерживается старыми версиями Firefox и IE.

В последнее время WHATWG уточнил сложение onlineи offlineсобытий, в случае , если вам нужно реагировать на navigator.onLineизменения.

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


источник
ОБНОВЛЕНИЕ: По состоянию на 2015 год, похоже, работает в большинстве браузеров, см. Диаграмму caniuse и статью
Ольга
8
window.navigator.onLine

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

window.addEventListener("offline", 
  ()=> console.log("No Internet")
);

и для проверки, если онлайн:

window.addEventListener("online", 
  ()=> console.log("Connected Internet")
);
Алиреза
источник
2
Вы должны быть осторожны с onLine. Браузеры определяют состояние онлайн совсем по-другому. Взгляните на developer.mozilla.org/en-US/docs/Web/API/NavigatorOnLine/onLine .
Андреас Баумгарт
1
Ваш ответ неверный. Свойство onLine не имеет ничего общего с подключением к Интернету. См. Ссылку выше о веб-API.
Александр В.
7

Я должен был сделать веб-приложение (на основе ajax) для клиента, который много работает со школами, у этих школ часто плохое интернет-соединение. Я использую эту простую функцию, чтобы определить, есть ли соединение, работает очень хорошо!

Я использую CodeIgniter и Jquery:

function checkOnline() {
    setTimeout("doOnlineCheck()", 20000);
}

function doOnlineCheck() {
    //if the server can be reached it returns 1, other wise it times out
    var submitURL = $("#base_path").val() + "index.php/menu/online";

    $.ajax({
        url : submitURL,
        type : "post",
        dataType : "msg",
        timeout : 5000,
        success : function(msg) {
            if(msg==1) {
                $("#online").addClass("online");
                $("#online").removeClass("offline");
            } else {
                $("#online").addClass("offline");
                $("#online").removeClass("online");
            }
            checkOnline();
        },
        error : function() {
            $("#online").addClass("offline");
            $("#online").removeClass("online");
            checkOnline();
        }
    });
}
ТЕО
источник
6

Ajax-вызов вашего домена - это самый простой способ определить, не подключены ли вы к сети.

$.ajax({
      type: "HEAD",
      url: document.location.pathname + "?param=" + new Date(),
      error: function() { return false; },
      success: function() { return true; }
   });

это просто чтобы дать вам концепцию, она должна быть улучшена.

Например, ошибка = 404 должна означать, что вы онлайн

harishr
источник
4

Я думаю, что это очень простой способ.

var x = confirm("Are you sure you want to submit?");
if (x) {
  if (navigator.onLine == true) {
    return true;
  }
  alert('Internet connection is lost');
  return false;
}
return false;
Пракаш Пажанисамы
источник
onLine не означает, что есть подключение к интернету. По словам developer.mozilla.org/en-US/docs/Web/API/NavigatorOnLine/onLine if the browser is not able to connect to a local area network (LAN) or a router, it is offline; all other conditions return true
Шмуэль Каменский
2

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

Я нашел способ обнаружить это, ища xhrStatus с кодом 404. Кроме того, я использую JSONP, чтобы обойти ограничение CORS. Код состояния, отличный от 404, показывает, что интернет-соединение не работает.

$.ajax({
    url:      'https://www.bing.com/aJyfYidjSlA' + new Date().getTime() + '.html',
    dataType: 'jsonp',
    timeout:  5000,

    error: function(xhr) {
        if (xhr.status == 404) {
            //internet connection working
        }
        else {
            //internet is down (xhr.status == 0)
        }
    }
});
wayofthefuture
источник
2
Это не работает с 10-5-2016 не уверен, почему просто не хотят, чтобы время других людей было потрачено впустую.
Брен
Я не думаю, что это будет работать для запрещенных и неверных ошибок запроса :)
Faisal Naseer
1

Мой путь.

<!-- the file named "tt.jpg" should exist in the same directory -->

<script>
function testConnection(callBack)
{
    document.getElementsByTagName('body')[0].innerHTML +=
        '<img id="testImage" style="display: none;" ' +
        'src="tt.jpg?' + Math.random() + '" ' +
        'onerror="testConnectionCallback(false);" ' +
        'onload="testConnectionCallback(true);">';

    testConnectionCallback = function(result){
        callBack(result);

        var element = document.getElementById('testImage');
        element.parentNode.removeChild(element);
    }    
}
</script>

<!-- usage example -->

<script>
function myCallBack(result)
{
    alert(result);
}
</script>

<a href=# onclick=testConnection(myCallBack);>Am I online?</a>
unxed
источник
1

Проблема некоторых методов, таких как, navigator.onLineзаключается в том, что они несовместимы с некоторыми браузерами и мобильными версиями. Мне очень помог вариант, который заключался в использовании классического XMLHttpRequestметода, а также предвидел возможный случай, когда файл был сохранен в кеше с ответом XMLHttpRequest.status, превышающим 200 и меньше чем 304.

Вот мой код:

 var xhr = new XMLHttpRequest();
 //index.php is in my web
 xhr.open('HEAD', 'index.php', true);
 xhr.send();

 xhr.addEventListener("readystatechange", processRequest, false);

 function processRequest(e) {
     if (xhr.readyState == 4) {
         //If you use a cache storage manager (service worker), it is likely that the
         //index.php file will be available even without internet, so do the following validation
         if (xhr.status >= 200 && xhr.status < 304) {
             console.log('On line!');
         } else {
             console.log('Offline :(');
         }
     }
}
Владимир Салгуэро
источник
0

Есть два ответа для двух разных senarios: -

  1. Если вы используете JavaScript на веб-сайте (т. Е. Или любой другой части интерфейса), то самый простой способ сделать это:

    <h2>The Navigator Object</h2>
    
    <p>The onLine property returns true if the browser is online:</p>
    
    <p id="demo"></p>
    
    <script>
      document.getElementById("demo").innerHTML = "navigator.onLine is " + navigator.onLine;
    </script>

  2. Но если вы используете js на стороне сервера (т. Е. Узел и т. Д.), Вы можете определить, что соединение потеряно, выполнив неудачные запросы XHR.

    Стандартный подход - повторить запрос несколько раз. Если этого не произойдет, предупредите пользователя, чтобы он проверил соединение, и завершите с ошибкой.

Ришабх Ананд
источник
0

заголовок запроса в ошибке запроса

$.ajax({
    url: /your_url,
    type: "POST or GET",
    data: your_data,
    success: function(result){
      //do stuff
    },
    error: function(xhr, status, error) {

      //detect if user is online and avoid the use of async
        $.ajax({
            type: "HEAD",
            url: document.location.pathname,
            error: function() { 
              //user is offline, do stuff
              console.log("you are offline"); 
              }
         });
    }   
});
Карима
источник
-1

Вот фрагмент вспомогательной утилиты, которую я имею. Это пространство имен javascript:

network: function() {
    var state = navigator.onLine ? "online" : "offline";
    return state;
}

Вы должны использовать это с обнаружением метода, иначе запустите «альтернативный» способ сделать это. Быстро приближается время, когда это будет все, что нужно. Другие методы - это хаки.

Питер Мортенсен
источник