2017-09-06 49 views
0

我要尋找一個解決方案來檢測移動設備是真的在線連接到互聯網。離子檢查互聯網連接

我已經試過明明以下方法在HTTP攔截:

if (navigator.connection.type != Connection.NONE) alert("you're online!") 

但問題是,誰是連接到一個沒有電腦網將會獲得消息的無線網絡用戶「你在線「雖然他們沒有互聯網。爲什麼?因爲在那種情況下,我們有navigator.connection.type = Connection.WIFI。

一個解決任何幫助嗎?

我能明顯的ping谷歌,但事實並非如此優雅,不知道谷歌會理解我超載他們的服務器。

我也想捕獲所有我失敗的http請求的響應,但基於該用戶是否具有互聯網或者請求失敗的另一個原因是我可以斷定不知道。

+0

如果您正在使用火力地堡,他們必須要檢查用戶的連接(我使用,似乎是工作的罰款這)一個非常有用的方式。除此之外,還有[this](https://stackoverflow.com/a/16242703/7468384)關於檢查與Angular的連接的問題和答案。 –

+1

那麼沒有系統事件會告訴你,如果你_really_有_working_連接。除了嘗試一個設置,比如說超時3000ms,沒有別的。您可以使用e GET調用服務器上的某個虛擬資源,或者像您說的那樣ping谷歌 - 我認爲它們可以處理您的流量:) – David

回答

0

可以ping喜歡的網站服務器,如果你得到任何響應,那麼 互聯網正在以其他方式連接檢查不

0

您可以獲取打電話,你在服務器端這只是一個200響應創建一個端點沒有數據的狀態。 我只能這樣做,如果檢測到navigator.connection.type的變化。 至於其他,我建議實行對每個請求的錯誤回調函數,你讓這樣就可以處理一個意外的連接丟失或任何比200和201

0

等您可以添加事件監聽用戶是否OnlineOffline

需要在平臺上增添準備爲您run功能如下:

$ionicPlatform.ready(function(){ 
document.addEventListener("offline", offlineCallBackFunction, false); 
document.addEventListener("online", onlineCallBackFunction, false); 

}) 

你的回調函數如下:

function offlineCallBackFunction() { 
      $ionicPopup.alert({ 
       title: "Internet Disconnected", 
       content: "Internet is disconnected on your device." 
      }); 

     } 

    function onlineCallBackFunction() { 
     $ionicPopup.alert({ 
      title: "Internet Connected", 
      content: "Internet is connected on your device." 
     }) 
     .then(function (result) { 
      window.location.reload(); 
     }); 
    } 

更新

上述方法檢測出你在網絡上或沒有,但爲你檢查你有互聯網接入或不通過調用你自己的Server (API)網址。

不要使用不屬於實際請求的主機進行測試,特別是如果它是不受控制的主機。也就是說,如果你想測試用戶是否可以達到www.example.com,請不要ping www.google.com。您的嘗試可能會被視爲惡意攻擊,尤其是如果您的應用程序變得流行。

+0

不幸的是,這與navigator.connection.type!= Connection.NONE的工作方式相同。如果我在沒有互聯網的情況下連接到WiFi網絡,我會收到「互聯網連接」消息。 – Robycool

+0

@Robycool,知道了,這部分告訴你,你已連接到網絡,嘗試訪問你的api'URL,如果失敗了,你就沒有互聯網訪問,而不是ping'Google' – Webruster

0

正如@大衛表示,沒有系統事件會告訴你,如果你真的有一個工作的互聯網連接。

邏輯

創建布爾vm.isInternetUp並假定用戶連接。有三個原因,用戶可以斷開連接:

  1. 如果脫機事件是由瀏覽器發射,這意味着沒有WIFI,3G或以太網連接
  2. 如果將設備連接到WiFi信道,但無線頻道沒有互聯網。
  3. 也可能有一個沒有互聯網的3G /以太網連接,但這與我們的案例不相關(未包含在本文中)。

現在我們只需要檢測何時發生這些情況之一,即vm.isInternetUp爲false。當該標誌轉爲脫機狀態時,我們開始一個帶有http請求的循環,直到我們獲得肯定的響應。

這很麻煩,但這樣我們就不會用連續的http請求來超載我們的服務器來檢查互聯網連接的狀態。當用戶重新聯機時,只有一個http將到達服務器。

有實現這種不同方式的代碼(看@ webruster與在線/離線事件的答案)。我選擇使用攔截器是因爲它最符合我的特定需求。

vm.isInternetUp = true //assume internet is up at startup 
    var interceptor = { 
    request: function(config) { 
     return vm.checkForInternet(config); 
    }, 
    responseError: function(reject){ 
     return vm.handleBadWifi(reject) 
    } 
    } 

對於原因1,我用角的HTTP request interceptor檢查在我們是否正在連接到WiFi每個請求。如果沒有,這意味着我們已經離線。

vm.checkForInternet = function(config) { 

    if (angular.isUndefined(window.Connection)) { 
     // The project is run in a web browser so window.Connection doesn’t exist. Assume we have internet. 
     console.log("window.Connection doesn't exist") 
     return config; 
    } 
    //if there is no internet 
    if (navigator.connection.type === Connection.NONE || !vm.isInternetUp) { 
     vm.isInternetUp = false 
     vm.reconnect(); 
     } 
     else { 
     console.log("connected but bad wifi") 
     } 
    } 
    return config; 
    } 

對於原因2,我使用$ http responseError interceptor攔截所有http請求。如文檔所述,reject.status = -1 usually means the request was aborted;我們從那裏得出的結論是沒有互聯網連接。

vm.handleBadWifi = function(reject) { 
     if (navigator.connection.type == Connection.WIFI && reject.status == -1) { 
     vm.isInternetUp = false 
     vm.checkForInternet(); //this will launch reconnection loop until connected again 
     } 
     return $q.reject(reject);  
    } 

最後,當我們收到一個肯定的請求時,重新連接循環停止。這很長,因爲我們不能像$ http攔截器那樣使用angular的$ http服務。使用$ http會導致循環依賴。

vm.reconnect = function() { 
    //Restart only if we were previously disconnected and after checking that we really have the internet 
    if (!vm.isInternetUp & !vm.reconnecting) { 
     console.log("attempting http call") 
     vm.reconnecting = true; 
     //backend-host is only pinged if internet was previously disconnected. In this way it does not overload the server. 
     //we don't use $http because that would induce a circular dependency (we're in an $http interceptor here). As this is a pure js http call this request will not be intercepted. 
     pureJsHttpGet(backendHost + 'projects/',vm.reconnectSuccess,vm.reconnectError) 
    }   
    } 
    vm.reconnectSuccess = function() { 
    vm.isInternetUp = true; 
    vm.reconnecting = false; 
    } 
    vm.reconnectError = function (error) { 
    $timeout(function() { 
     vm.reconnecting = false; 
     vm.checkForInternet(); 
    },3000) 
    console.error("Did not manage to find an internet connection. Retrying in 3 sec", error) 
    if (navigator.connection.type === Connection.WIFI){ 
     //create a fake reject error so that the wifi errorhandler knows the request failed 
     var reject = {status:-1} 
     vm.handleBadWifi(reject)  
    } 
    } 
    function pureJsHttpGet(theUrl, successCallback, errorCallback){ 
     var xmlHttp = new XMLHttpRequest(); 
     xmlHttp.onreadystatechange = function() { 
      if (xmlHttp.readyState == 4 && xmlHttp.status == 200) 
      successCallback(xmlHttp.responseText); 
      else if (xmlHttp.readyState == 4 && xmlHttp.status == 0) 
      errorCallback(xmlHttp) 
     } 
     xmlHttp.open("GET", theUrl, true); // true for asynchronous 
     xmlHttp.send(null); 
    }