【问题标题】:Angular: $resource update fire PUT request on second call onlyAngular:$resource update 仅在第二次调用时触发 PUT 请求
【发布时间】:2013-06-18 18:31:44
【问题描述】:

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

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 请求仅在第二次和之后的点击时触发,从不会从第一次触发。

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

【问题讨论】:

    标签: angularjs angularjs-directive angularjs-scope


    【解决方案1】:

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

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

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

    在 AngularJS 中,$resource 基于$http,因此上述讨论也适用于$resource

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

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

    【讨论】:

      猜你喜欢
      • 2019-08-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-14
      • 2018-05-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多