【问题标题】:Online/Offline App in AngularAngular 中的在线/离线应用程序
【发布时间】:2013-10-28 22:53:21
【问题描述】:

我正在使用 Angular 开发一个应用程序,该应用程序对几个 Web 服务进行多次调用。我想为应用程序开发一个离线组件,以便它将某些 web 服务结果缓存到 LocalStorage 并在连接离线时使用它们。

这部分相当简单,我最头疼的部分是应用离线时如何进行逻辑分支。

这是我目前的流程:

  1. 用户加载页面
  2. Web 服务调用照常进行
  3. $http 拦截器查找 404 错误并标记 $rootScope.isOnline 布尔标志以指示我们处于离线状态,否则如果没有 404 则我们标记为在线

我希望我的代码以可维护的方式根据此标志进行分支。因此,我正在考虑使用依赖注入来注入调用 Web 服务的“在线”服务,或者注入与 LocalStorage 结果(如果存在)交互的“离线”服务。

我可以根据在线/离线标志来注入依赖项注入,像这样注入正确的服务吗?

.factory('AuthService', ['$rootScope', '$injector', function($rootScope, $injector) {
    if($rootScope.isOnline) {
        return $injector.get('OnlineAuthService');
    }
    else {
        return $injector.get('OfflineAuthService');
    }
}])

.service('OnlineAuthService', ['$rootScope', '$http', '$location', 'serviceEndpoint', 'securityEndpoint', 'organisationId', function ($rootScope, $http, $location, serviceEndpoint, securityEndpoint, organisationId) {
    this.ensureSession = function (data) {
        // Do some connection to the webservice
    };
}])

.service('OfflineAuthService', ['$rootScope', function ($rootScope) {
    this.ensureSession = function (data) {
        // Do some LocalStorage stuff
    };
}])

AuthService.ensureSession(data);

我遇到的问题是 $rootScope.isOnline 在第一次调用我的 web 服务之前没有标记为离线,所以即使连接离线,依赖注入也会查看 $rootScope.isOnline 并注入 OnlineAuthService。

这是在 Angular 中开发在线/离线应用程序的正确方法还是有更好的方法?

【问题讨论】:

  • 基本上我会通过在 JavaScript 中创建一个虚假接口来解决这个问题,该接口同时接受服务,并在运行时确定使用哪一个。通过这种方式,可以在知道应用程序是否在线之前注入服务。我还会让它在内部处理初始化调用,以避免处理来自试图获取初始数据的控制器的竞争条件。
  • @shaunhusain 听起来很有趣...你能分享一个如何工作的例子吗?
  • 这里是一个plnkr,代码更详细:plnkr.co/edit/BXyZVU7uoKkJO4KQOs3R?p=info
  • 可以在初始化 Angular 之前进行初始测试(不要自动初始化 Angular),并将全局变量从测试传递给您的服务。测试完成后调用 angular bootstrap ......我认为这与@shaunhusain 的建议有关。也不确定您在离线时会收到 401 吗?
  • @charlietfl 猜我可以这样做,之前看到了 angular bootstrap 方法,但是如果可以的话,我试图避免使用全局变量并采用更 Angular 的方式。我在离线时收到 404,而不是 401。

标签: javascript web-services angularjs dependency-injection


【解决方案1】:

有很多方法可以做到这一点。看看这个简化的 plunker:

http://plnkr.co/edit/CpiJaF480Mai050b63RC?p=preview

这里的想法是,您拥有由服务返回的单例服务对象,但是随着在线/离线更改,您会复制不同的函数方法。

还有许多其他方法可以做到这一点,例如添加间接级别(例如,创建一个可以请求当前活动服务的服务)。

您不能简单地使用角度注入来实现,因为工厂调用和服务调用都会被调用一次,并且只会被调用一次,并且只会为服务名称注册一个实例(每次注入时它们都不会被调用)。

【讨论】:

  • 这很棒,效果很好,非常感谢您抽出时间给我一个例子!
  • 是的,这基本上就是我要说的,除了可能拥有与最终实现所需的“接口”或功能相同的服务。此处示例中显示的内容是相同的,只是让两个服务具有相同的可用功能,并根据 is online 属性的当前状态切换要使用的服务。如果在线状态在某个时刻发生变化,您可能希望“AuthService”还依赖其他一些服务来调用“重新初始化”数据。
  • 这很好,但有没有办法以更“角度”的方式实现相同的目标。 IE。将registerOnlineOfflineService 方法封装在工厂/提供者中而不是污染全局命名空间?
  • 全局命名空间是指 $rootScope 吗?如果是,那么可以确定,只需更改 $watch 以监视服务上的功能,而不是将 isOnline 放在范围内。
猜你喜欢
  • 1970-01-01
  • 2015-11-01
  • 2017-12-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-07
  • 2014-11-21
相关资源
最近更新 更多