我在作用域中有一个属性为外部对象的id,我也有一个过滤器可以将这个id扩展为一个完整的对象,如下所示:
{{ typeId | expandType }}
过滤器:
.filter('expandType', ['TypeService', function (tsvc) {
return function (id) {
return tsvc.types.get({ id: id });
}
}])
其中tsvc.types.get()是具有添加的缓存选项的普通资源获取方法。
.factory('TypeService', ['$resource', function ($resource) {
var typeResource = $resource('/api/types/:id', { id: '@id' }, {
get: { method: 'GET', cache: true, params: { id: '@id' } }
});
return {
types: typeResource
}
}])
据我所知,角度在第一个之后运行额外的消化只是为了确保没有任何改变。但显然在下一个摘要中,过滤器返回一个不同的对象,我得到了infdig错误(摘要在无限循环中执行)。
我希望如果资源被缓存,它将始终从缓存中返回相同的对象。我可以确认在执行get()时只有一次访问服务器,因此缓存正在运行。
如何使其工作并使用过滤器将ID扩展为完整对象?
答案 0 :(得分:0)
尽管可能,将promises绑定到视图通常不是一个好主意。在您的情况下,过滤器会在每个摘要上重新评估,并引用https://docs.angularjs.org/api/ng/service/$http:
启用缓存后,$ http将来自服务器的响应存储在指定的缓存中。下次发出相同的请求时,响应将从缓存中提供,而不向服务器发送请求。
请注意,即使响应是从缓存提供的,数据的传递也是异步的,就像实际请求一样。
为了澄清,ngResource在内部使用$http
。
您仍然可以使用从控制器调用它的过滤器:
app.filter('expandType', function ($http) {
return function (id) {
return $http.get('data.json');
};
});
app.controller('MainCtrl', function ($scope, expandTypeFilter) {
var typeId = 'hello';
expandTypeFilter(typeId).success(function (data) {
$scope.expandedTypeId = data[typeId];
});
});
Plunker:http://plnkr.co/edit/BPS9IY?p=preview。
使用这种方法,如果您缓存响应的唯一原因是为了避免重复调用服务器,您现在可以停止缓存它以便以后获取新数据,但这当然取决于您的需求。
答案 1 :(得分:0)
我真的很想使用过滤器,因为它在整个应用程序中使用过,我不想让我的控制器混乱。在这一点上,我出来的解决方案看起来如下:
.filter('expandType', ['TypeService', function (tsvc) {
var cache = {};
return function (id) {
if (!id) {
return '';
}
var type = cache[id];
if (!type) {
tsvc.types.get({ id: id }).$promise.then(function (data) {
cache[id] = data;
});
cache[id] = {}
return cache[id];
}
else {
return type;
}
}
}])