如何检测联机/脱机状态何时更改

时间:2014-05-25 02:18:39

标签: angularjs

我想知道什么时候互联网连接丢失并重新获得,以便我可以在一个警告说“呐喊”,“没有互联网”和“#34;以及包含从我的服务器派生的数据的Google地图或网格。

This related questionthis other related question认为他们有答案,但他们没有。

他们的解决方案适用于Chrome版本34.0.1847.137 m,MS IE v11.0.x.x,但不适用于FireFox v29.0.1,因此我正在寻找适用于所有这三种浏览器的解决方案。


[更新] AS @Quad指出,有不同的方式来定义在线意味着什么。我将它定义为"我可以获取我需要向用户显示的数据吗?"。


我有几个服务,负责从多个服务器获取数据(什么是最好的?一个参数化的服务?每个服务器一个服务?每个服务器每个数据类型一个服务?我在想什么?后者,因为每个服务可以映射到映射到视图的控制器。但我是Angular的新手,所以可能是错误的。)

此外,我编写了一个服务,负责在连接丢失时尝试重新连接。

任何尝试$http.get并获得404的人都可以调用该服务   1)广播没有互联网(所以没有其他人会尝试连接)
  2)经常尝试连接到我的服务器和
  3)成功后,停止连接尝试并广播该应用现在再次在线。

然而,这似乎非常笨拙,两个相关问题提供的解决方案似乎很优雅 - 除了FF :-(

我不能在这里重新发明轮子。其他人如何做到这一点?事实上,我很惊讶,还没有一个"官方"角度解决方案

3 个答案:

答案 0 :(得分:26)

我知道的最好方法是截取HTTP处理程序,如果它是401/501 / etc然后根据

处理它

例如:

angular.module('myApp', ['myApp.services'], 
    function ($httpProvider) {

    var interceptor = ['$rootScope', '$q', function ($rootScope, $q) {

        function success(response) {
            return response;
        }

        function error(response) {
            var status = response.status; // error code

            if ((status >= 400) && (status < 500)) {
                $rootScope.broadcast("AuthError", status);
                return;
            }

            if ( (status >= 500) && (status < 600) ) {
                $rootScope.broadcast("ServerError", status);
                return;
            }

            // otherwise
            return $q.reject(response);

        }

        return function (promise) {
            return promise.then(success, error);
        }

    }];
    $httpProvider.responseInterceptors.push(interceptor);

然后在你的代码中监听on,只需添加

$rootScope.$on("ServerError", someServerErrorFunction);

您还可以添加内部标志,并仅在该标志更改时进行广播。

但是,如果您正在寻找一个解决方案,其中用户没有过于频繁地与服务器通信,您可以添加一个每分钟左右ping服务器的部分,但这可能无法响应您的喜好。

答案 1 :(得分:7)

在我的应用程序中,我有一个/ping端点,我每隔X秒轮询一次。这当然可能不适合大型应用程序。

angular.module("pingMod", [])
    .run(function ($http, $interval) {
        var TIME = 60000;
        function ping() {
            $http.get("/ping");
        }
        $interval(ping, TIME);
    });

我将它与@Gil建议的HTTP拦截器结合使用。当我们获得0状态时,我们处于离线状态。对于使用$ http。

的任何AJAX调用,都会触发此操作

以下是使用$http的拦截器代码。您当然可以决定使用Restangular,但这取决于您的应用需求。

angular.module("myModule", [])
    .config(function ($httpProvider) {
    var interceptor = [
        '$q',
    function ($q) {
        return function (promise) {
            return promise.then(function (response) {
                return response;
            }, function (response) {
                if (response.status === 0) {
                    // We're offline!
                }
                return $q.reject(response);
            });
        };
    }];
    $httpProvider.responseInterceptors.push(interceptor);
})

答案 2 :(得分:5)

您可以通过轮询服务器或仅等待响应失败来检测 disconnect 。除非您有特殊要求,否则后一种方法更可取。检测到断开连接后,将需要使用轮询来检测重新连接。

以角度实现此功能的一种优雅方式是使用$http监视所有网络活动,Restangular是所有XHR活动流过的可注入服务。 {{3}}用以下内容抽象出来:

  • RestangularProvider.addFullRequestInterceptor :在向服务器发送任何数据之前,您可以完全访问该请求。

  • RestangularProvider.setErrorInterceptor :在服务器发出每个错误响应后调用。

以下是使用Restangular实现状态观察器的伪代码:

var last_request

RestangularProvider.addFullRequestInterceptor:
  last_request = Save last request

RestangularProvider.setErrorInterceptor:
    - Display the 'offline' status message to user
    - Use $interval to periodically re-submit last_request until successful
    - When periodic re-submission succeeds, hide 'offline' status message

即使你没有特别要求使用Restangular的答案,你确实说你正在寻找一个既定的模式,Restangular内置了一些非常易于使用但功能强大的模式。当然,这里提出的相同想法可以仅用$http来实现。