我有一个带有自定义更新方法的资源:
angular.module('user.resources', ['ngResource']).
factory('User', function($resource) {
var User = $resource('/user/:id', {}, {
update: {
method: 'PUT'
}
});
User.prototype.update = function(cb) {
console.log('foo');
return User.update({
id: this._id
}, angular.extend({}, this, {
_id: undefined
}), cb);
};
我正在通过范围将此资源传递给自定义指令:
directive('avatarUpload', function($http) {
return {
restrict: 'E',
scope: {
model: '='
}, ...
我在btn点击中调用指令控制器中的update方法:
$scope.model.update(function() {
console.log('bar');
});
让我困惑的行为是第一次点击按钮'foo'而不是'bar',点击第二次打印'bar',然后'foo'。再点击总是打印'bar'然后'foo'。
PUT请求仅从第二次点击和之后的点击,而不是从第一次点击。
注意:我一直在控制器中使用该资源更新方法,直到尝试从指令调用它。我正在使用角1.1.4 我执行此资源传递是因为我希望该指令适用于不同类型的资源。
答案 0 :(得分:7)
在没有看到实时代码示例的情况下很难肯定,但我认为您正在使用1.1.x系列中的AngularJS(所谓的“不稳定分支”)。如果是这样,您遇到的问题与AngularJS中的新功能相关联 - 版本1.1.4中引入的HTTP请求拦截器(此commit)。
新引入的请求拦截器基于$q
(基于承诺),在AngularJS中,世界承诺仅作为$digest
周期的一部分进行解析。换句话说,您需要处于“AngularJS世界”($digest
周期)中才能解决承诺。
使用基于承诺的请求拦截器,可以在进行$http
呼叫之前解决。如前所述,此承诺只能在您输入$digest
周期时解决。如果从AngularJS(DOM事件,setTimeout等)之外启动$http
,则不会发生这种情况。
在AngularJS中,$resource
基于$http
,因此上述讨论也适用于$resource
。
所以,假设上述假设是正确的,并且你正在从AngularJS之外发起$resource
调用(你正在谈论一个自定义指令,所以我会赌一个DOM事件)你应该只是将$resource
电话打包到scope.$apply
。
请注意,将$resource
电话打包到$timeout
(如另一个回复中所示),同时将“修复”您的问题(它将强制执行$ digest循环,因此承诺将得到解决) 这不是正确的方法。问题是它会强制浏览器离开当前的JavaScript上下文并输入重绘上下文。它会使您的应用程序变慢,并可能导致UI闪烁。