Phát hiện kết nối Internet đang ngoại tuyến?


246

Làm cách nào để phát hiện kết nối Internet đang ngoại tuyến trong JavaScript?


Nếu bạn có thể hoặc đã sử dụng websockets - websockets có Sự kiện Đóng phải được gọi nếu người dùng bị mất kết nối với máy chủ.
Simon

Câu trả lời:


135

Bạn có thể xác định rằng kết nối bị mất bằng cách thực hiện các yêu cầu XHR không thành công .

Cách tiếp cận tiêu chuẩn là thử lại yêu cầu một vài lần. Nếu không được, hãy thông báo cho người dùng để kiểm tra kết nối và không thành công .

Sidenote: Để đặt toàn bộ ứng dụng ở trạng thái "ngoại tuyến" có thể dẫn đến nhiều công việc xử lý dễ bị lỗi .. các kết nối không dây có thể đến và đi, v.v. Vì vậy, cách tốt nhất của bạn có thể là thất bại một cách duyên dáng, bảo toàn dữ liệu và cảnh báo người dùng .. cho phép họ cuối cùng khắc phục sự cố kết nối nếu có và tiếp tục sử dụng ứng dụng của bạn với một lượng tha thứ hợp lý.

Sidenote: Bạn có thể kiểm tra một trang web đáng tin cậy như google để kết nối, nhưng điều này có thể không hoàn toàn hữu ích vì chỉ cố gắng thực hiện yêu cầu của riêng bạn, bởi vì trong khi Google có thể có sẵn, ứng dụng của riêng bạn có thể không, và bạn vẫn sẽ phải xử lý vấn đề kết nối của riêng bạn. Cố gắng gửi ping đến google sẽ là một cách tốt để xác nhận rằng chính kết nối internet bị hỏng, vì vậy nếu thông tin đó hữu ích cho bạn, thì nó có thể gây rắc rối.

Sidenote : Gửi Ping có thể đạt được giống như cách bạn thực hiện bất kỳ loại yêu cầu ajax hai chiều nào, nhưng gửi ping đến google, trong trường hợp này, sẽ đặt ra một số thách thức. Đầu tiên, chúng ta sẽ có các vấn đề liên tên miền tương tự thường gặp khi thực hiện liên lạc Ajax. Một tùy chọn là thiết lập proxy phía máy chủ, trong đó chúng tôi thực sự pinggoogle (hoặc bất kỳ trang web nào) và trả lại kết quả ping cho ứng dụng. Đây là một cái bẫy-22bởi vì nếu kết nối internet thực sự là vấn đề, chúng tôi sẽ không thể truy cập máy chủ và nếu sự cố kết nối chỉ nằm trên miền của chúng tôi, chúng tôi sẽ không thể phân biệt được. Các kỹ thuật tên miền chéo khác có thể được thử, ví dụ: nhúng iframe trong trang của bạn trỏ đến google.com, sau đó bỏ phiếu iframe để thành công / thất bại (kiểm tra nội dung, v.v.). Nhúng một hình ảnh có thể không thực sự cho chúng ta biết bất cứ điều gì, bởi vì chúng ta cần một phản hồi hữu ích từ cơ chế giao tiếp để đưa ra kết luận tốt về những gì đang diễn ra. Vì vậy, một lần nữa, việc xác định trạng thái của kết nối internet nói chung có thể gặp nhiều rắc rối hơn giá trị của nó. Bạn sẽ phải cân nhắc các tùy chọn này cho ứng dụng cụ thể của mình.


84
"Sidenote" lặp đi lặp lại nghe có vẻ như Dwight Schrute nói "Câu hỏi ..." :-)
Brian Kelly

19
Tại sao "bắt-22" in đậm?
mã hóa

33
Bây giờ vào năm 2012, bạn có thể kiểm tra biến navigator.onLine;)
João Pinto Jerónimo

13
navigator.online/offline cũng không đáng tin cậy, vì những lý do rất giống nhau. Xem stackoverflow.com/questions/3181080/
Mạnh

17
Bạn có thể muốn xem Offline.js , một thư viện mã nguồn mở được xây dựng cho mục đích này.
Adam

51

IE 8 sẽ hỗ trợ window.navigator.onLine .

Nhưng tất nhiên điều đó không giúp ích gì với các trình duyệt hoặc hệ điều hành khác. Tôi dự đoán các nhà cung cấp trình duyệt khác sẽ quyết định cung cấp thuộc tính đó cũng như tầm quan trọng của việc biết trạng thái trực tuyến / ngoại tuyến trong các ứng dụng Ajax.

Cho đến khi điều đó xảy ra, XHR hoặc một Image()hoặc <img>yêu cầu có thể cung cấp một cái gì đó gần với chức năng bạn muốn.

Cập nhật (2014/11/16)

Các trình duyệt chính hiện hỗ trợ thuộc tính này, nhưng kết quả của bạn sẽ thay đổi.

Trích dẫn từ Tài liệu Mozilla :

Trong Chrome và Safari, nếu trình duyệt không thể kết nối với mạng cục bộ (LAN) hoặc bộ định tuyến thì nó sẽ ngoại tuyến; tất cả các điều kiện khác trở lại true. Vì vậy, trong khi bạn có thể cho rằng trình duyệt ngoại tuyến khi nó trả về một falsegiá trị, bạn không thể cho rằng một giá trị thực sự nhất thiết có nghĩa là trình duyệt có thể truy cập internet. Bạn có thể nhận được thông báo sai, chẳng hạn như trong trường hợp máy tính đang chạy phần mềm ảo hóa có bộ điều hợp ethernet ảo luôn được "kết nối". Do đó, nếu bạn thực sự muốn xác định trạng thái trực tuyến của trình duyệt, bạn nên phát triển các phương tiện bổ sung để kiểm tra.

Trong Firefox và Internet Explorer, chuyển đổi trình duyệt sang chế độ ngoại tuyến sẽ gửi một falsegiá trị. Tất cả các điều kiện khác trả về một truegiá trị.


5
navigator.onLine là một phần của HTML5 - các trình duyệt khác đã có phiên bản phát triển cung cấp nó - nó đã có sẵn trong Firefox 3 ngày hôm nay.
olliej

-Nhưng tiếc là không có sẵn trong các phiên bản IE trước, chúng tôi thường phải hỗ trợ.
keparo

22
navigator.onLine hiển thị trạng thái của trình duyệt chứ không phải kết nối thực tế. Vì vậy, bạn có thể cài đặt trình duyệt của mình thành onLine nhưng nó thực sự sẽ thất bại vì kết nối bị hỏng. navigator.onLine sẽ chỉ sai nếu trình duyệt được đặt thành duyệt ngoại tuyến.

5
nếu tôi tắt WI-FI trên Nexus7 của mình, trang vẫn nói rằng navigator.onLine là TRUE. Xấu ...
walv

42

Hầu như tất cả các trình duyệt chính hiện nay đều hỗ trợ thuộc window.navigator.onLinetính và các sự kiện tương ứng onlineofflinecửa sổ:

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

Hãy thử đặt hệ thống hoặc trình duyệt của bạn ở chế độ ngoại tuyến / trực tuyến và kiểm tra bảng điều khiển hoặc thuộc window.navigator.onLinetính để biết các thay đổi giá trị. Bạn có thể kiểm tra nó trên trang web này là tốt.

Lưu ý tuy nhiên trích dẫn này từ Tài liệu Mozilla :

Trong Chrome và Safari, nếu trình duyệt không thể kết nối với mạng cục bộ (LAN) hoặc bộ định tuyến thì nó sẽ ngoại tuyến; tất cả các điều kiện khác trở lại true. Vì vậy, trong khi bạn có thể cho rằng trình duyệt ngoại tuyến khi trả về một falsegiá trị , bạn không thể cho rằng một truegiá trị nhất thiết có nghĩa là trình duyệt có thể truy cập internet . Bạn có thể nhận được thông báo sai, chẳng hạn như trong trường hợp máy tính đang chạy phần mềm ảo hóa có bộ điều hợp ethernet ảo luôn được "kết nối". Do đó, nếu bạn thực sự muốn xác định trạng thái trực tuyến của trình duyệt, bạn nên phát triển các phương tiện bổ sung để kiểm tra.

Trong Firefox và Internet Explorer, chuyển đổi trình duyệt sang chế độ ngoại tuyến sẽ gửi một falsegiá trị. Cho đến Firefox 41, tất cả các điều kiện khác trả về một truegiá trị; kể từ Firefox 41, trên OS X và Windows, giá trị sẽ tuân theo kết nối mạng thực tế.

(nhấn mạnh là của riêng tôi)

Điều này có nghĩa là nếu window.navigator.onLinefalse(hoặc bạn nhận được một offlinesự kiện), bạn được đảm bảo không có kết nối Internet.

trueTuy nhiên, nếu đó là (hoặc bạn nhận được một onlinesự kiện), điều đó chỉ có nghĩa là hệ thống được kết nối với một số mạng, tốt nhất. Điều đó không có nghĩa là bạn có quyền truy cập Internet chẳng hạn. Để kiểm tra điều đó, bạn vẫn sẽ cần sử dụng một trong những giải pháp được mô tả trong các câu trả lời khác.

Ban đầu tôi dự định đăng bài này như một bản cập nhật cho câu trả lời của Grant Wagner , nhưng dường như quá nhiều chỉnh sửa, đặc biệt là xem xét rằng bản cập nhật 2014 không phải từ anh ấy .


Câu trả lời tốt nhất. Cảm ơn.
vibs2006

1
Gần đây tôi có cơ hội làm việc một chút về hành vi ngoại tuyến. Các sự kiện rất tuyệt để sử dụng, NHƯNG ios safari sẽ tạo ra vấn đề. Khi bạn bật internet trên điện thoại, các sự kiện ngoại tuyến / trực tuyến sẽ bị trì hoãn tối đa 2 giây và điều đó có thể gây ra vấn đề vì lý do hiển thị trực quan, vì bạn không thể dự đoán được tương lai. Đó chỉ là điều tôi muốn đề cập và có thể giúp đỡ ai đó.
TeeJaay

38

Có một số cách để làm điều này:

  • Yêu cầu AJAX đến trang web của riêng bạn. Nếu yêu cầu đó không thành công, rất có thể đó là lỗi kết nối. Các JQuery tài liệu có một phần về xử lý các yêu cầu AJAX thất bại . Cảnh giác với Chính sách Xuất xứ tương tự khi thực hiện việc này, điều này có thể ngăn bạn truy cập các trang web bên ngoài miền của bạn.
  • Bạn có thể đặt onerrormột img, như

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

    Phương pháp này cũng có thể thất bại nếu hình ảnh nguồn được di chuyển / đổi tên và thường sẽ là một lựa chọn kém hơn so với tùy chọn ajax.

Vì vậy, có một số cách khác nhau để thử và phát hiện điều này, không có cách nào hoàn hảo, nhưng trong trường hợp không có khả năng nhảy ra khỏi hộp cát trình duyệt và truy cập trực tiếp trạng thái kết nối mạng của người dùng, chúng dường như là những lựa chọn tốt nhất.


36
 if(navigator.onLine){
  alert('online');
 } else {
  alert('offline');
 }

11
Nó luôn trả về ĐÚNG nếu trên trình duyệt.
Slavcho

2
Đầu tiên tôi đã cố gắng vô hiệu hóa CHỈ LAN, nhưng nó luôn trả về ĐÚNG. Vì vậy, khi tôi vô hiệu hóa tất cả các mạng (LAN2, Virtual Box, v.v.), nó đã trả về SAI.
Slavcho

3
Câu trả lời này trùng lặp một số câu trả lời hiện có từ 3 năm trước.
JasonMArcher

2
Nó không kiểm tra kết nối internet, nó chỉ kiểm tra kết nối LAN một mình
Suganth G

Làm việc cho tôi trong HTML 5, JavaScript, trong mac book (sử dụng wifi) thậm chí hoạt động trong thiết bị di động. nhưng vấn đề là - khi wifi trên nó trả về TRUE mỗi lần tôi tắt wifi ngược lại.
S.Yadav

11

API bộ đệm ứng dụng HTML5 chỉ định navigator.onLine, hiện có sẵn trong các bản beta của IE8, WebKit (ví dụ: Safari) và đã được hỗ trợ trong Firefox 3


11

Bạn có thể sử dụng hàm gọi lại của $ .ajax ()error , sẽ kích hoạt nếu yêu cầu không thành công. Nếu textStatusbằng chuỗi "hết thời gian" thì có lẽ kết nối bị ngắt:

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

Từ tài liệu :

Lỗi : Một chức năng được gọi nếu yêu cầu không thành công. Hàm được truyền ba đối số: Đối tượng XMLHttpRequest, một chuỗi mô tả loại lỗi xảy ra và một đối tượng ngoại lệ tùy chọn, nếu xảy ra. Các giá trị có thể có cho đối số thứ hai (ngoài null) là "hết thời gian", "lỗi", "không sửa đổi" và "trình phân tích cú pháp". Đây là một sự kiện Ajax

Ví dụ:

 $.ajax({
   type: "GET",
   url: "keepalive.php",
   success: function(msg){
     alert("Connection active!")
   },
   error: function(XMLHttpRequest, textStatus, errorThrown) {
       if(textStatus == 'timeout') {
           alert('Connection seems dead!');
       }
   }
 });

9

Như olliej đã nói, sử dụng thuộc tính navigator.onLinetrình duyệt tốt hơn là gửi các yêu cầu mạng và, theo đó là developer.mozilla.org/En/Online_and_offline_events , nó thậm chí còn được hỗ trợ bởi các phiên bản Firefox và IE cũ.

Gần đây, WHATWG đã chỉ định bổ sung onlineofflinecác sự kiện, trong trường hợp bạn cần phản ứng với các navigator.onLinethay đổi.

Cũng xin chú ý đến liên kết được đăng bởi Daniel Silveira, điều này chỉ ra rằng việc dựa vào các tín hiệu / thuộc tính đó để đồng bộ hóa với máy chủ không phải lúc nào cũng là một ý tưởng hay.


CẬP NHẬT: Tính đến năm 2015, nó dường như đang hoạt động trên hầu hết các trình duyệt, xem biểu đồbài viết về
Olga

8
window.navigator.onLine

là những gì bạn đang tìm kiếm, nhưng một vài thứ ở đây cần thêm vào, trước tiên, nếu đó là thứ gì đó trên ứng dụng của bạn mà bạn muốn tiếp tục kiểm tra (như để xem liệu người dùng có đột nhiên ngoại tuyến hay không, điều này đúng trong trường hợp này, thì bạn sẽ cũng cần lắng nghe để thay đổi), để bạn thêm trình lắng nghe sự kiện vào cửa sổ để phát hiện bất kỳ thay đổi nào, để kiểm tra xem người dùng có ngoại tuyến không, bạn có thể thực hiện:

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

và để kiểm tra nếu trực tuyến:

window.addEventListener("online", 
  ()=> console.log("Connected Internet")
);

2
Bạn phải cẩn thận với onLine. Trình duyệt xác định trạng thái trực tuyến rất khác nhau. Hãy xem developer.mozilla.org/en-US/docs/Web/API/NavigatorOnLine/onLine .
Andreas Baumgart

1
Câu trả lời của bạn là sai. Thuộc tính 'onLine' không liên quan gì đến kết nối internet. Xem tài liệu tham khảo ở trên về api web.
Alexandre V.

7

Tôi đã phải tạo một ứng dụng web (dựa trên ajax) cho một khách hàng làm việc nhiều với các trường học, những trường này thường có kết nối internet xấu Tôi sử dụng chức năng đơn giản này để phát hiện nếu có kết nối, hoạt động rất tốt!

Tôi sử dụng CodeIgniter và 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

một cuộc gọi ajax đến miền của bạn là cách dễ nhất để phát hiện nếu bạn ngoại tuyến

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

Đây chỉ là để cung cấp cho bạn khái niệm, nó cần được cải thiện.

Ví dụ: error = 404 vẫn có nghĩa là bạn trực tuyến


4

Tôi nghĩ đó là một cách rất đơn giản.

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 không có nghĩa là có kết nối internet. Theo nhà phát 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
triển.mozilla.org/en-US/docs/Web/API/NavigatorOnLine/onLine

2

Tôi đang tìm kiếm một giải pháp phía khách hàng để phát hiện xem internet có bị sập hay máy chủ của tôi bị sập không. Các giải pháp khác mà tôi thấy dường như luôn phụ thuộc vào tệp hoặc hình ảnh tập lệnh của bên thứ 3, mà theo tôi dường như nó sẽ không vượt qua được thử thách của thời gian. Một tập lệnh hoặc hình ảnh được lưu trữ bên ngoài có thể thay đổi trong tương lai và khiến mã phát hiện bị lỗi.

Tôi đã tìm thấy một cách để phát hiện nó bằng cách tìm kiếm một xhrStatus với mã 404. Ngoài ra, tôi sử dụng JSONP để bỏ qua hạn chế CORS. Mã trạng thái khác 404 cho thấy kết nối internet không hoạt động.

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

2
Điều đó không hoạt động kể từ ngày 10-5-2016, không chắc tại sao chỉ muốn lãng phí thời gian của người khác.
Bren

Tôi không nghĩ vì vậy nó sẽ hoạt động đối với các lỗi yêu cầu bị cấm và xấu :)
Faisal Naseer

1

Cách của tôi

<!-- 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>

1

Vấn đề của một số phương pháp như navigator.onLinelà chúng không tương thích với một số trình duyệt và phiên bản di động, một tùy chọn giúp tôi rất nhiều là sử dụng XMLHttpRequestphương pháp cổ điển và cũng thấy trước trường hợp có thể tệp được lưu trữ trong bộ đệm có phản hồiXMLHttpRequest.status lớn hơn 200 và nhỏ hơn 304.

Đây là mã của tôi:

 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

Có 2 câu trả lời cho hai kịch bản khác nhau: -

  1. Nếu bạn đang sử dụng JavaScript trên một trang web (nghĩa là hoặc bất kỳ phần giao diện người dùng nào) Cách đơn giản nhất để làm điều đó là:

    <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. Nhưng nếu bạn đang sử dụng js ở phía máy chủ (ví dụ: nút, v.v.), bạn có thể xác định rằng kết nối bị mất bằng cách thực hiện các yêu cầu XHR không thành công.

    Cách tiếp cận tiêu chuẩn là thử lại yêu cầu một vài lần. Nếu không được, hãy thông báo cho người dùng để kiểm tra kết nối và không thành công.


0

yêu cầu đầu trong lỗi yêu cầu

$.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

Đây là một đoạn của một tiện ích trợ giúp tôi có. Đây là javascript được đặt tên:

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

Bạn nên sử dụng phương pháp này với phương pháp phát hiện khác để loại bỏ cách 'thay thế' này. Thời gian đang đến rất nhanh khi đây sẽ là tất cả những gì cần thiết. Các phương pháp khác là hack.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.