4

这是我之前的 AngularJS 问题的后续。

我正在尝试复制本视频教程中提到的 $resource 服务的功能:链接

在本教程中,展示了您可以使用异步调用更新范围变量及其视图。首先,这是设置的资源:

$scope.twitter = $resource('http://twitter.com/:action',
    {action: 'search.json', q: 'angularjs', callback: 'JSON_CALLBACK'},
    {get: {method: 'JSONP'}});

然后在get资源上调用该函数以进行 ajax 调用并更新必要的范围变量:

$scope.twitterResult = $scope.twitter.get();

这里发生的是$scope.twitter.get()立即返回一个空对象引用。然后,当 ajax 请求返回时,该对象将使用来自 Twitter 的数据进行更新。然后视图会更新所有 {{twitterResult}} 实例,您会看到返回的数据。

我不明白的是,当对象在异步回调中更新时,范围如何知道值已更改?

我不这么认为——回调必须在作用域上调用某种更新函数,对吧?但如果是这样,这是如何完成的?我听说过一个$apply可能是答案的函数——但是你如何从资源内部引用 $scope.$apply() 呢?

我创建了一个 JSFiddle 来说明这个问题:http: //jsfiddle.net/Qcz5Y/10/

(编辑:这是一个较新的 JSFiddle 使用不同的异步调用来说明使用 ajax 调用而不是 setTimeout 的问题:http: //jsfiddle.net/Qcz5Y/14/

在此示例中,您将看到一个控制器和一个资源。控制器的作用域有一个属性 ,fruit它一开始就设置为一个对象。当您单击“获取新水果”时,该属性设置为fruitResource.get(),这将立即返回一个空对象。然后它进行异步调用,最后执行一个回调,更新最初返回的对象的值。

发生这种情况时, 的值$scope.fruit会正确更新为回调中设置的值。但它并没有反映在视图中。

如果您单击“打印当前水果”,它将记录到控制台的当前值$scope.fruit。这只是为了检查;它具有更新视图的副作用。

我觉得我需要在函数底部做类似 $scope.$apply() 的事情get_callback(你会在代码中看到它)。那是正确的做法吗?如果是这样,我如何在fruitResource 中获得对$scope 的引用?我知道我可能可以作为参数传入$scopefruitResource.get()然后以这种方式引用它,但是顶部提到的示例中的 $resource.get() 函数不需要这样做,所以我希望 AngularJS 提供一些方法自动从服务中获取范围。

谢谢!

4

2 回答 2

9

我发现你可以传入$rootScope一个服务,然后调用$apply它。因此,当您想更新视图时,只需执行$rootScope.$apply().

这是更新的 JSFiddle:http: //jsfiddle.net/Qcz5Y/11/

于 2012-08-19T01:38:49.493 回答
1

实际上模拟 Resource 的行为非常简单,归结为进行异步调用并立即返回空结果。然后,当数据确实从服务器到达时,需要更新返回的引用。这是使用您的用例的示例:

   get: function() {
        var fruit = {};

        // Asynchronous call that executes a callback. Simulation of ajax/db request            
        $timeout(function() {
            fruit.type = ['banana', 'strawberry', 'watermellon', 'grape'][Math.floor(Math.random() * 4)];
            fruit.count = [1, 2, 3, 4][Math.floor(Math.random() * 4)];
        }, 2000);

        return fruit;
    } 

这是完整的 jsFiddle:http: //jsfiddle.net/pkozlowski_opensource/sBgAT/1/

请注意,我正在使用 Angular 的 $timeout 服务来模拟异步调用,因为 $timeout 会在需要时负责调用 $apply,因此无需任何手动干预即可触发 UI 重新绘制。自从您尝试使用需要调用 $apply 的 setTimout 以来,您遇到了一些问题。

于 2012-08-19T08:04:07.947 回答