2017-09-06 52 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); 
    }