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

Maw*_*awg 26 angularjs

我想知道什么时候互联网连接丢失并重新获得,以便我可以在一个警告"哎呀,没有互联网"和谷歌地图或包含从我的服务器派生的数据的网格之间切换.

这个相关问题其他相关问题认为他们有答案,但他们没有.

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


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


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

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

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

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

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

Jda*_*ern 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);
Run Code Online (Sandbox Code Playgroud)

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

$rootScope.$on("ServerError", someServerErrorFunction);
Run Code Online (Sandbox Code Playgroud)

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

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

  • 谢谢,我从SO那里获得了很多帮助,很高兴能够开始帮助 (2认同)
  • 因此,如果您获得的HTTP状态代码> = 500且<600,您知道用户是否处于脱机状态?(我的[类似问题](http://stackoverflow.com/questions/27451186/http-error-handling-distinguishing-user-offline-from-other-errors)指示我这里) (2认同)
  • 很好的答案!+1.我认为你应该更新它,因为`responseInteceptors`在当前的角度1.x版本中已被弃用.从我的测试中,如果由于没有互联网连接而导致角度http请求失败,则返回的状态为"-1".它可能不是标准响应,但这是我在检测cordova-angular应用程序中没有连接的方法(使用角度1.4.8) (2认同)

Sam*_*m P 7

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

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

我将它与@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);
})
Run Code Online (Sandbox Code Playgroud)


Gil*_*man 5

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

以角度实现此功能的一种优雅方式是使用$http可注入服务监视所有网络活动,所有XHR活动都通过该服务流动.Restangular为您提供以下内容:

  • 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
Run Code Online (Sandbox Code Playgroud)

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