我有以下控制器代码:
.controller('Controller1', function ($scope, MyService) {
var promise = MyService.getData();
promise.then(function(success) {
console.log("success");
}, function(error) {
console.log("error");
}, function(update) {
console.log("got an update!");
}) ;
}
在My services.js中:
.factory('MyService', function ($resource, API_END_POINT, localStorageService, $q) {
return {
getData: function() {
var resource = $resource(API_END_POINT + '/data', {
query: { method: 'GET', isArray: true }
});
var deferred = $q.defer();
var response = localStorageService.get("data");
console.log("from local storage: "+JSON.stringify(response));
deferred.notify(response);
resource.query(function (success) {
console.log("success querying RESTful resource")
localStorageService.add("data", success);
deferred.resolve(success);
}, function(error) {
console.log("error occurred");
deferred.reject(response);
});
return deferred.promise;
}
}
})
但由于某些原因,deferred.notify
调用似乎从未在控制器内执行和接收。我是不是有什么不对劲?我不确定如何让通知执行。
3条答案
按热度按时间kyvafyod1#
来源:http://www.bennadel.com/blog/2800-forcing-q-notify-to-execute-with-a-no-op-in-angularjs.htm
强制执行$Q.Notify()
Notify()事件的美妙之处在于,我们的数据访问层可以使用它来提供“立即可用的、但过时的”数据,同时仍然使用.Resolve()事件来处理实时数据。这使调用上下文(您的控制器)能够很好地洞察和控制缓存的数据集,以及它(控制器)是否甚至想要合并缓存的数据。
但是,我们遇到了一点种族问题。拥有缓存数据的数据访问服务在将承诺返回到调用上下文之前需要调用.tify()。这意味着您的控制器在调用.tify()之后绑定到Notify事件。从哲学的Angular 来看,这应该很好-承诺(以及几乎所有事件驱动的内容)旨在异步调用绑定,以便创建统一的访问。
然而,从实际的Angular 来看,事情并不是那么简单。虽然AngularJS遵循这一理念,但它也添加了一些优化以减少处理。具体地说,在我们的例子中,AngularJS不会在延迟对象中调度回调处理,除非它发现至少有一个回调被绑定(否则它认为世界没有在监听)。因此,我们的控制器永远不会收到有关缓存数据的通知。
为了解决这个问题,我们可以让服务层在Notify事件调用.fy()之前将一个no-op(无操作)函数绑定到Notify事件。这样,当AngularJS确实调用.tify()时,它将看到至少注册了一个回调,并且它将在下一个计时(通过$rootScope.$valAsync()实现)调度挂起队列的刷新。这允许我们的控制器得到关于缓存数据的通知,即使它在调用.fy()之后绑定到Notify事件。
为了实际了解这一点,我创建了一个FriendService,它通过两种不同的方法返回数据。这两种方法都尝试通过.tify()返回缓存数据,然后通过.Resolve()返回“实时”数据。这两种方法之间的唯一区别是,一种方法在调用.fy()之前将no-op绑定到Notify事件
如您所见,控制器将相同的处理程序绑定到承诺的“Resolve”和“Notify”事件。通过这种方式,可以统一处理缓存数据和实时数据。唯一的区别是它调用哪个服务层方法-get()和getWithNoop()。而且,如果我们调用几次.get(),然后调用几次.getWithNoop(),我们可以在控制台中看到区别。
lpwwtiir2#
我试着重现你的问题。看起来,您不能直接对Promise调用
notify
,而必须 Package 到$apply
调用中。另请参阅此处的
$q
文档。引用示例中的准确行:
由于此fn在事件循环的未来回合中执行异步,因此我们需要将代码 Package 到$Apply调用中,以便正确地观察模型更改。
您可以自己尝试一下,然后稍微更改一下代码:
k10s72fa3#
我设法将Notify Package 在$Timeout函数中,从而使其正常工作:
看起来在返回Promise对象之前不能调用Notify,这有点道理。