将 $watch 设置为 AngularJS 中服务函数的 return 值

Setup a $watch to a return value of a service's function in AngularJS

TL;DR 如何在控制器中将 $watch 设置为 DI 服务的函数 return 值?

我的应用程序有一项服务,以便在控制器之间轻松共享数据。我正在尝试为来自控制器的这些变量之一设置 $watch。但是,我想通过服务的 getter 访问该特定变量。

这是控制器中的代码

    //this is the controller
    var vm = this;
    vm.isValidPhase = false;

    activate();

    ////////////////

    function activate() {
        vm.isValidPhase = userProgressService.getCurrentPhaseValidity();

        $scope.$watch('userProgressService.getCurrentPhaseValidity()',
                     function(newValue) {
            vm.isValidPhase = newValue;
        });
    }

userProgressService 我有:

   //this is the service
   var current = {
        phaseNumber : 0,
        phaseValidity : false,
        phase   : {},
        userInput   : {}
    };

    // ... ... ...

    var exports = {
        getCurrentPhaseData  : getCurrentPhaseData,
        getCurrentPhaseValidity : getCurrentPhaseValidity,
        setCurrentPhaseValidity : setCurrentPhaseValidity,
        getExistingUserInput : getExistingUserInput
    };

    return exports;

    // ... ... ...

    function getCurrentPhaseValidity() {
        return current.phaseValidity;
    }

    // ... ... ...

在我使用 mocha、bard、chaisinon 对控制器进行的单元测试中,我正在做:

describe('initial state', function () {
    it('should be an invalid phase', function () {
        expect(userProgressService.getCurrentPhaseValidity(),
               'in service function').to.be.false;
        expect(controller.isValidPhase,
               'in controller scope').to.be.false;
    });
});

我在第二个断言中遇到错误:

AssertionError: in controller scope: expected undefined to be false

现在,通过尝试注释和取消注释,我注意到问题出在控制器中的 $watch 表达式。但是我不知道它有什么问题...我做错了什么?

正如您在评论中看到的@JBNizet 指出 $watch 表达式是错误的,相反,我应该关注函数本身,因为 $scope 中没有定义服务.然而,他也让我意识到,至少在这种情况下,我不需要设置 $watch。用他自己的话说

[...] expose the function of the service in the scope (i.e. $scope.getCurrentPhaseValidity = userProgressService.getCurrentPhaseValidity;), and use <button ng-show="getCurrentPhaseValidity()">

我按照他说的做了,将控制器范围更改为

//... controller ...
vm.isValidPhase = userProgressService.getCurrentPhaseValidity;

现在我可以在控制器下的 HTML 中使用 ng-showisValidPhase 类似的东西了。

正如预期的那样,它起作用并符合我想要观察变量的目的,即 activate/deactivate 基于其值的按钮。

据我所知,此解决方案涵盖了您遇到的大部分相关问题。