首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么这里需要angular $apply?

为什么这里需要angular $apply?
EN

Stack Overflow用户
提问于 2014-05-10 00:01:42
回答 2查看 151关注 0票数 2

请考虑以下控制器的angularjs代码:

代码语言:javascript
复制
(function (app) {
    var controller = function ($scope, $state, datacontext) {
        $scope.$parent.manageTitle = "Account Management";
        $scope.accounts = [];

        var init = function () {
            getRecords();
        };

        var getRecords = function () {
            return datacontext.getAccounts().then(function (data) {
                $scope.$apply(function () {
                    $scope.accounts = data;
                });
            });
        };

        init();
    };

    app.controller("accountsCtrl", ["$scope", "$state", "datacontext", controller]);
})(angular.module("app"));

删除数据包装器并在getRecords方法中只保留"$scope.accounts = $scope.$apply“会破坏代码。检索数据,但是html中的ng-repeat指令不会自动更新。我正在尝试使用整个$apply/$digest模型,但在这种情况下,似乎不应该需要$apply。

我做错了什么吗?

谢谢。

<->

好的,谢谢你的回复。下面是数据上下文。它使用Breeze。我仍然不明白问题出在哪里--我就是不明白为什么上面的代码需要$apply。

代码语言:javascript
复制
(function (app) {
    var datacontext = function () {
        'use strict';
        breeze.config.initializeAdapterInstance('modelLibrary', 'backingStore', true);
        breeze.config.initializeAdapterInstance("ajax", "angular", true);
        breeze.NamingConvention.camelCase.setAsDefault();

        var service;
        var manager = new breeze.EntityManager('api/ProximityApi');
        var entityQuery = breeze.EntityQuery;

        var queryFailed = function (error) {
        };

        var querySuccess = function (data) {
            return data.results;
        };

        var getAccounts = function () {
            var orderBy = 'accountName';
            return entityQuery.from('Accounts')
                .select('id, accountName')
                .orderBy(orderBy)
                .using(manager)
                .execute()
                .then(querySuccess, queryFailed);
        };

        service = {
            getAccounts: getAccounts
        };

        return service;
    };
    app.factory('datacontext', [datacontext]);
})(angular.module('app'));

再次感谢!

EN

回答 2

Stack Overflow用户

发布于 2014-05-10 22:11:21

谢谢你的回答。贾里德-你说的没错。默认情况下,Breeze不使用angular $q承诺,而是使用第三方Q.js承诺。因此,我需要$apply将VM同步到视图。然而,最近Breeze团队创建了angular.breeze.js,它允许Breeze代码使用angular promises。通过在应用程序中包含angular.breeze模块,所有Breeze代码都将使用原生angular promises和$http。

这解决了我的问题,我可以删除$apply调用。

请参阅:http://www.breezejs.com/documentation/breeze-angular-service

票数 3
EN

Stack Overflow用户

发布于 2014-05-10 07:15:35

需要使用$apply函数的原因是使用Breeze to返回数据的结果。$apply函数用于获取angular,以便对所有内部监视运行摘要并相应地更新作用域。当所有更改都发生在角度范围内时,这是不需要的,因为它会自动执行此摘要。在你的代码中,因为你使用的是Breeze,所以更改发生在angular作用域之外,因此你需要让angular手动运行摘要,这对于发生在angular之外的任何事情都是正确的(jQuery,其他框架等等)。确实,Breeze正在使用promises更新数据,但是Angular不知道如何处理promise返回后的更改,因为它超出了作用域。如果你使用的是angular服务和promises,那么视图将会自动更新。如果您的代码工作正常,那么以这种方式使用$apply将是正确的方式。

我唯一建议的是更改调用apply的方式,以确保它仅在当前没有另一个摘要正在进行时才会运行,因为这可能会导致摘要错误。我建议你这样调用这个函数:

代码语言:javascript
复制
if(!$scope.$$phase){$scope.$apply(function () {
   $scope.accounts = data;
});

或者,另一种选择是像这样的SafeApply编写一个围绕$apply函数的自定义包装器

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/23569128

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档