1

我有一个具有自定义更新方法的资源:

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 单击时调用指令控制器中的更新方法:

$scope.model.update(function() {
  console.log('bar');
});

令我困惑的行为是第一次单击按钮打印'foo'而不是'bar',第二次单击它打印'bar',然后是'foo'。任何更多的点击总是打印'bar'然后'foo'。

PUT 请求仅在第二次点击和之后的点击中触发,而不是从第一次触发。

注意:我一直在控制器中使用该资源更新方法,直到尝试从指令中调用它。我正在使用 angular 1.1.4 我执行此资源传递,因为我希望该指令适用于不同类型的资源。

4

1 回答 1

7

如果没有看到实时代码示例,很难确定,但我认为您使用的是 1.1.x 系列的 AngularJS(所谓的“不稳定分支”)。如果是这样,您面临的问题与 AngularJS 中的新功能有关 - 版本 1.1.4 中引入的 HTTP 请求拦截器(此提交)。

新引入的请求拦截器是$q基于 - 的(基于承诺的),并且在 AngularJS 世界中,承诺仅作为$digest循环的一部分解决。换句话说,您需要在“AngularJS 世界”($digest循环)中才能解决承诺。

使用基于 Promise 的请求拦截器,有一个 Promise 需要在$http调用之前解决。如前所述,只有当您进入$digest循环时,才能解决此承诺。$http如果您从 AngularJS(DOM 事件、setTimeout 等)外部启动,则不会发生这种情况。

在 AngularJS$resource中是基于$http所以上面的讨论也适用于$resource

因此,假设上述假设是正确的,并且您正在$resource从 AngularJS 外部发起调用(您正在谈论自定义指令,所以我敢打赌 DOM 事件),您应该简单地将$resource调用包装到scope.$apply.

请注意,将$resource调用包装到$timeout(如另一个响应中所建议的那样),while 将“修复”您的问题(它将强制 $digest 循环,因此承诺将得到解决)这不是正确的方法。问题是它会强制浏览器离开当前的 JavaScript 上下文并进入重绘上下文。它会使您的应用程序变慢,并可能导致 UI 闪烁。

于 2013-06-24T08:47:41.480 回答