在 Angular 控制器中处理异步更新的正确方法

Proper Way to Handle Asynchronous Updates in Angular Controller

这是我的设置 -- 我有一个控制器,它使用的服务可以完成一些工作,然后异步地 returns 数据。在这种情况下,数据是通过超时返回的,但在现实生活中,这会做一些更有趣的事情:

查看:

<div ng-controller="RootController as root">

  <h1>Angular Project</h1>
  <div ng-show="{{root.greeting}}">
    <p>{{root.greeting}}</p>
  </div>

</div>

控制器:

(function(){

  'use strict';

  function RootController(greetingService) {

    var vm = this;
    vm.greeting = '';

    // startup logic
    activate();

    function activate() {
        greetingService.greeting().then(
          function( response ) {
              vm.greeting = response;
          },
          function( error ) {
              vm.greeting = error;
          }
        );
    }
  }
  RootController.$inject = ['greeting'];
  angular.module('app.core').controller('RootController', RootController);

})();

服务:

(function() {
  'use strict';

  // Greeting Service
  function greeting( $timeout ) {

    // public API
    var service = {
        greeting:   greeting
    };
    return service;

    // internal functions
    function greeting() {
        return $timeout( function() {
            return 'Hello world!'; 
        }, 1000 );
    }

  }

  temp.$inject = ['$timeout'];
  angular.module('app.core').factory( 'greeting', greeting );

})();

问题:

  1. 为什么当超时解决并且我的控制器中发生 vm.greeting 分配时我的视图没有更新?我看到有人描述"inside Angular vs outside Angular",但在我看来我没有去过"outside Angular"这里。

  2. 我知道我可以调用 $scope.$apply(),但我遇到了“digest is already in progress”错误,而且我似乎又不应该这样做。

  3. 有没有更好的方法来组织我的组件?我还尝试过通过 $rootScope 广播事件并在控制器中编写事件处理程序,但这种安排表现出相同的结果(即当异步模型更改发生时视图未更新)。

ng-show 不需要花括号

https://docs.angularjs.org/api/ng/directive/ngShow

改变

<div ng-show="{{root.greeting}}">

<div ng-show="root.greeting">

您构建代码的方式与我通常采用的方式大不相同。查看此 link 以获得出色的风格指南。http://toddmotto.com/opinionated-angular-js-styleguide-for-teams/

至于您的问题,Angular 使用 $scope 将控制器中的值绑定到视图。所以你的控制器应该注入 $scope 然后你可以做 $scope.greeting 代替 vm.greeting.