从$ scope调用时不会触发角度资源调用。$ watch

时间:2013-07-23 09:58:35

标签: angularjs coffeescript angularjs-directive angularjs-scope

我创建了一个监视day属性的指令,并在属性值发生变化时检索远程资源。 CoffeeScript代码:

angular.module('app.directives').directive 'myDirective', ['$timeout', ($timeout)->

    DirectiveController=($scope, activityResource)->

        # Load activities
        load= ()->
            activityResource.get {
                day: $scope.day
                environment_id: $scope.environment.id
            },
            (data)->
                $scope.activities = data.activities

        # Watch environment and reload activities
        $scope.$watch 'environment', (value) ->
            load()

        # Watch selected day to reload activities
        $scope.$watch 'day', (value) ->
            load()
...
]

每次load更改时都会调用day方法,但结果回调永远不会触发。网络检查显示请求未发送到远程端。我找到的唯一解决方法是使用load服务推迟执行$timeout方法:

        $scope.$watch 'day', (value) ->
            $timeout (()-> load()), 10

我怀疑与范围生命周期有关的问题,但我无法弄清楚为什么我不得不将调用推迟到资源。

更新

资源源代码:

resources = angular.module('app.resources', ['ngResource'])

...

resources.factory 'app.activityResource', ['$resource', 'app.endpoint', ($resource, endpoint)->
  $resource "#{endpoint()}/user/environments/:environment_id/activities/:id/:verb",
  {environment_id: "@environment_id", id: "@id"},
  latest:
    method : 'GET'
    params:
      verb: 'latest'
  annual:
    method : 'GET'
    params:
      verb: 'annual'
]

我还在代码摘录中添加了第二个监视属性(environment),用作查询资源的参数。

更新2

我不知道它是否相关,但我们正在使用CORS访问远程端(这似乎运作良好)。

1 个答案:

答案 0 :(得分:1)

您没有看到请求被触发的原因是,作为$ http调用的一部分,配置作为承诺传递给每个拦截器。

https://github.com/angular/angular.js/blob/b99d064b6ddbcc9f59ea45004279833e9ea82928/src/ng/http.js#L665-L670

在角度中,$ q承诺仅在$ digest周期开始时解决。因此,在$ digest循环发生之前,您的HTTP请求甚至不会被触发,这就是为什么您会看到围绕它的$ timeout会有所帮助(超时会导致$ digest)。

https://github.com/angular/angular.js/blob/2a5c3555829da51f55abd810a828c73b420316d3/src/ng/q.js#L160 https://github.com/angular/angular.js/blob/3967f5f7d6c8aa7b41a5352b12f457e2fbaa251a/src/ng/rootScope.js#L503-L516

您还可以通过重新创建您正在查看的错误条件并观看网络请求来验证这一点。运行此操作后,您应该看到您的请求已关闭:

angular.element( "[ng-app]" ).scope().$digest()

该代码会在$ rootScope上触发$ digest循环,导致您未解决的承诺得到解决。

请参阅此问题以获取更多讨论,因为我同意这是令人惊讶的行为。

https://github.com/angular/angular.js/issues/2881