【发布时间】:2014-10-11 00:30:45
【问题描述】:
我有一个在 Chrome 扩展中运行的简单 AngularJS 应用程序,它使用了存储 API。存储的异步性质存在问题;我已将存储抽象为“UserService”,将数据设置和获取为工厂:
app.factory('UserService',
function($q, AppSettings) {
var defaults = {
api: {
token: AppSettings.environments[1].api.token
},
email: ''
};
var service = {
user: {},
save: function() {
chrome.storage.sync.set({'user': angular.toJson(service.user)});
},
restore: function() {
var deferred = $q.defer();
chrome.storage.sync.get('user', function(data) {
if(!data) {
chrome.storage.sync.set({'user': defaults});
service.user = defaults;
} else {
service.user = angular.fromJson(data.user);
}
deferred.resolve(service);
});
return deferred.promise;
}
};
// set the defaults
service.restore().then(function(data) {
console.log(data);
return data;
});
});
上面的console.log() 调用会按预期转储数据。但是,当我在其他工厂中包含 UserService(我有一个使用用户特定 API 令牌的 APIService)时,UserService 参数在下面的代码中被标记为“未定义”:
app.factory('APIService',
function($resource, $http, UserService, AppSettings) {
var token = UserService.user.api.token;
...
});
我确信我没有完全掌握 Angular 承诺模式,即在整个应用程序中使用已解决的承诺。
更新代码:
app.factory('UserService',
function($q, AppSettings) {
var defaults = {
api: {
token: AppSettings.environments[1].api.token
},
email: ''
};
var service = {
user: {},
save: function() {
chrome.storage.sync.set({'user': angular.toJson(service.user)});
},
restore: function() {
var deferred = $q.defer();
chrome.storage.sync.get('user', function(data) {
if(!data) {
chrome.storage.sync.set({'user': defaults});
service.user = defaults;
} else {
service.user = angular.fromJson(data.user);
}
deferred.resolve(service.user);
});
return deferred.promise;
}
};
// set the defaults
service.restore().then(function(data) {
console.log(data);
return data;
});
return service;
});
编辑/附加信息:
好的,接近了。已经重构,以便我正确返回对象,但现在的问题是当APIService 被创建并尝试使用UserService 对象的属性时,它们根本不存在,因为它们仅在之后创建异步恢复方法已解决。所以不可能访问UserService.user.api.token 属性,因为它当时不存在,所以问题是,如果当时不可用,当我需要它时如何在 APIService 中获取该数据?我试图避免将APIService 的全部内容放入一个回调中,该回调在假设的新UserService.get() 方法之后触发,该方法在承诺解决时调用回调。任何最终指导表示赞赏。
【问题讨论】:
-
您的意思是
deferred.resolve(data);而不是deferred.resolve(service);?您可以调用 restore 方法。并链接到UserService.restore().then((data)=>{ var token = data.api.token; }) -
我将解析的
data值包含在更大的服务对象中。如果我在 APIService 中调用 restore 方法,那我不是必须将那个工厂的所有代码都放在.then()方法中吗?如果我还有其他要解决的承诺怎么办? -
下面的答案是正确的。你需要返回服务:app.factory('UserService', function($q, AppSettings) { .... return service;});