【问题标题】:Issue calling service inside app.config在 app.config 中发出调用服务
【发布时间】:2017-01-11 02:20:16
【问题描述】:

现在调用我在 app.config 中使用 LokiJS (http://lokijs.org/#/) 创建的服务时遇到一些问题。

我知道在 Angular 中,您实际上不应该在应用程序启动期间尝试使用配置部分内的服务,但是从堆栈溢出拼凑的其他一些答案中,我已经能够实际访问该服务,但我仍然遇到现在似乎是 LokiJS 特有的问题。

以下是我的服务副本:

(function(){

angular.module('LocalStorage', [])
  .service('localStorageService', [
    'Loki',
    '$q',
   function(Loki, $q) {

      var self = this;

      var db;
      var localstorage;

      self.initDB = function() {
           var adapter = new LokiCordovaFSAdapter({"prefix": "loki"});
           // Store to a file localstorage.json
           db = new Loki('localstorage.json',
                   {
                       autosave: true,
                       autosaveInterval: 1000, // 1 second
                       adapter: adapter
                   });

          // Testing purposes only
                   console.log('end of Init DB'); 
       };

      self.getLocalStorage = function() {

          console.log('calling get local storage');

          return $q(function (resolve, reject) {
              var options = {};

              console.log('inside the return');

              db.loadDatabase(options, function () {
                  console.log('right before call getcollection');
                  localstorage = db.getCollection('localstorage');

                  console.log('grabbed local storage collection');

                  if (!localstorage) {
                    console.log('localstorage did not exist so MAKING NEW ONE');
                    localstorage = db.addCollection('localstorage');

                  }

                  resolve(localstorage.data);
              });
          });
      };

        self.getFromLocalStorage = function(value) {

          var returnValue = localstorage.findOne({key: value});

          return returnValue;
        };

        self.addToLocalStorage = function(key, value) {
          // Format record to be stored
          var data = {'key': key, 'value': value};

          // Check if this 'key' already exists in localstorage
          if (self.getFromLocalStorage(key)) {
            console.log('ATTEMPTING TO UPDATE INSTEAD OF INSERT');
            // If it exists then run an 'update'
            //var lokiValue = self.getFromLocalStorage(key)['$loki'];
            var lokiValue = self.getFromLocalStorage(key);

            // Replace with new value
            lokiValue['value'] = value;

            // Now update
            localstorage.update(lokiValue);
          } else {
            console.log('ATTEMPTING TO INSERT INSTEAD OF UPDATE');
            // If key does not exist, insert
            localstorage.insert(data);
          }
      };

       self.deleteFromLocalStorage = function(value) {

          // Grab object that you are trying to delete
          var obj = self.getFromLocalStorage(value);

          localstorage.remove(obj);
      };

      // TODO Should only be used for testing purposes
      self.deleteDatabase = function() {

        console.log('ATTEMPTING TO DELETE DATABASE');
        db.deleteDatabase();
      };

    }]);
  })();

还有 app.config:

app.config([
    '$stateProvider',
    '$httpProvider',
    'jwtInterceptorProvider',
    'localStorageServiceProvider',
    function ($stateProvider, $httpProvider, jwtInterceptorProvider, localStorageServiceProvider) {

        localStorageServiceProvider.$get().initDB();

        localStorageServiceProvider.$get().getLocalStorage()
       .then(
        function (result) {
                 // Auth interception
                 console.log("INFO", 'Create auth interceptor');
                 jwtInterceptorProvider.tokenGetter = function (jwtHelper) {
                     var token = localStorageServiceProvider.$get().getFromLocalStorage('token');
                     return token;
                 };
                 $httpProvider.interceptors.push('jwtInterceptor');
                   },
           function (error) {
               // handle errors here
               console.log('Something crazy happened with grabbing collection, This should not happen.');
            }
         );

    }]);

所以基本上发生的事情是代码永远不会在“console.log('inside return');”之后执行。 localStorageService 内的 getLocalStorage() 函数内的日志记录语句。我从来没有看到任何过去的日志出现,所以似乎“db.loadDatabase()”甚至从未真正运行过。

如果是这种情况,我对如何在调用 getLocalStorage() 之前正确执行“initDB()”函数感到困惑。

我不确定这是否是由于某些 Loki 依赖问题导致无法正确访问它,因为我试图在 app.config 中调用此函数,或者完全是其他的。

我什至尝试在 app.config 中从该服务运行这些函数的原因是我希望能够存储通过 JwtInterceptorProvider 访问的令牌。

对此的任何帮助将不胜感激,我对 Angular 和 Loki 都很陌生,所以我确信这里只是缺少一个小问题,或者我有这种结构设置的方式那是不合适的。谢谢!

【问题讨论】:

    标签: javascript angularjs dependencies lokijs


    【解决方案1】:

    服务不应该用$get() 实例化,因为自然原因它们在config 中不可用,这只会破坏事情。它们不再是单例(除了这使它们无法测试)。

    这个

        localStorageServiceProvider.$get().initDB();
    

    还有这个

        localStorageServiceProvider.$get().getLocalStorage()
    

    引用localStorageService 的两个不同实例。

    这里有几个竞争条件。这里的主要问题是localStorageService 是异步的。不管是在配置还是运行阶段调用,当应用程序进入运行阶段,$http被实例化并开始发出请求时,这段代码

                 jwtInterceptorProvider.tokenGetter = ...;
                 $httpProvider.interceptors.push('jwtInterceptor');
    

    可能还没有被执行。

    没有办法“暂停”Angular 应用程序初始化来解决应用程序范围的依赖关系。

    解决这个问题的第一种方法是使用路由器解析器,它应该从根状态继承以确保它肯定会在每个状态上触发。

    一些提供者可以在服务实例化之后进行配置。如果在引导应用程序后配置它们可能会很有用。这会使保修失效,不能保证这样的黑客服务不会造成副作用。

    app.config(($provide, $httpProvider, jwtInterceptorProvider, $stateProvider) => {
      $stateProvider.state('root', {
        abstract: true,
        resolve: { init, 'initResolver' }
      });
      ...
    
      // don't even needed if initResolver is defined as a function in config
      $provide.value($httpProvider);
      $provide.value(jwtInterceptorProvider);
    });
    
    app.factory('initResolver', (localStorageService, $httpProvider, jwtInterceptorProvider) => {
      localStorageService.getLocalStorage()...
      jwtInterceptorProvider.tokenGetter = ...;
      $httpProvider.interceptors.push('jwtInterceptor');
    });
    

    第二种方法是推迟引导过程。如果应用程序依赖项是非 Angular 的,这可能是一个不错的选择,就像在这种情况下一样。由于Loki 数据库应该被应用程序本身重用,因此将localStorageService 重构为仅使用现有对象是有益的(它甚至可能不需要包装其方法)

    var lsDb = new Loki(...);
    var ls;
    
    lsDb.loadDatabase(..., () => {
      ls = lsDb.addCollection('localstorage');
    
      angular.module('app')
      .constant('localStorageDb', localStorageDb);
      .factory('localStorageService', () => {
        return ls;
      });
    
      angular.bootstrap(document, ['app']);
    })
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-08-31
      • 2013-03-02
      • 2013-08-17
      • 2011-02-10
      • 2012-04-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多