在 app.config 内发布调用服务
Issue calling service inside app.config
现在在我的 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.');
}
);
}]);
所以基本上发生的事情是代码永远不会执行到 localStorageService 内 getLocalStorage() 函数内的 "console.log('inside the return');" 日志语句。我从来没有看到任何过去出现的日志,所以似乎 "db.loadDatabase()" 甚至从来没有成为 运行。
如果是这种情况,我对 "initDB()" 函数在调用 getLocalStorage() 之前如何正确执行感到困惑。
我不确定这是不是因为某些 Loki 依赖性问题导致无法正确访问它,因为我试图在 app.config 内部调用此函数,或者完全是其他原因。
我什至尝试 运行 从 app.config 中的此服务中获取这些功能的原因是因为我希望能够存储通过 JwtInterceptorProvider 访问的令牌。
如能提供任何帮助,我们将不胜感激,我对 Angular 和 Loki 都很陌生,所以我确信这里只有一个小问题我遗漏了,或者有办法解决我有这个结构设置是不合适的。谢谢!
不应使用 $get()
实例化服务,由于自然原因,它们在 config
中不可用,这只会破坏事情。他们不再是单身人士(除了这使他们无法测试的事实)。
这个
localStorageServiceProvider.$get().initDB();
还有这个
localStorageServiceProvider.$get().getLocalStorage()
引用 localStorageService
的两个不同实例。
这里有几个竞争条件。这里的主要问题是 localStorageService
是异步的。不管是在config阶段还是在运行阶段调用,在app进入运行阶段,$http
实例化并开始请求时,这段代码
jwtInterceptorProvider.tokenGetter = ...;
$httpProvider.interceptors.push('jwtInterceptor');
可能还没有执行。
无法通过 'pause' 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']);
})
现在在我的 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.');
}
);
}]);
所以基本上发生的事情是代码永远不会执行到 localStorageService 内 getLocalStorage() 函数内的 "console.log('inside the return');" 日志语句。我从来没有看到任何过去出现的日志,所以似乎 "db.loadDatabase()" 甚至从来没有成为 运行。
如果是这种情况,我对 "initDB()" 函数在调用 getLocalStorage() 之前如何正确执行感到困惑。
我不确定这是不是因为某些 Loki 依赖性问题导致无法正确访问它,因为我试图在 app.config 内部调用此函数,或者完全是其他原因。
我什至尝试 运行 从 app.config 中的此服务中获取这些功能的原因是因为我希望能够存储通过 JwtInterceptorProvider 访问的令牌。
如能提供任何帮助,我们将不胜感激,我对 Angular 和 Loki 都很陌生,所以我确信这里只有一个小问题我遗漏了,或者有办法解决我有这个结构设置是不合适的。谢谢!
不应使用 $get()
实例化服务,由于自然原因,它们在 config
中不可用,这只会破坏事情。他们不再是单身人士(除了这使他们无法测试的事实)。
这个
localStorageServiceProvider.$get().initDB();
还有这个
localStorageServiceProvider.$get().getLocalStorage()
引用 localStorageService
的两个不同实例。
这里有几个竞争条件。这里的主要问题是 localStorageService
是异步的。不管是在config阶段还是在运行阶段调用,在app进入运行阶段,$http
实例化并开始请求时,这段代码
jwtInterceptorProvider.tokenGetter = ...;
$httpProvider.interceptors.push('jwtInterceptor');
可能还没有执行。
无法通过 'pause' 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']);
})