AngularJS:在控制器中为提供者的$get方法使用$watch

AngularJS:在控制器中为提供者的$get方法使用$watch,angularjs,angular-ui-router,Angularjs,Angular Ui Router,我一直在四处寻找,但找不到解决方案。我有一个提供程序,它只使用$get函数返回RANDOM,还有另一个方法将RANDOM设置为数组中的随机字符串。在从配置中设置RANDOM之后,我可以从配置中访问它的当前值,但是即使存在$watch,控制器也不会检测到对RANDOM的更改。为了您的方便,我在下面附上了我的代码 提供者: app.provider('sets', function (){ var sets= ['gogreen', 'gored', 'tekkon', 'temple', 'com

我一直在四处寻找,但找不到解决方案。我有一个提供程序,它只使用$get函数返回RANDOM,还有另一个方法将RANDOM设置为数组中的随机字符串。在从配置中设置RANDOM之后,我可以从配置中访问它的当前值,但是即使存在$watch,控制器也不会检测到对RANDOM的更改。为了您的方便,我在下面附上了我的代码

提供者:

app.provider('sets', function (){
var sets= ['gogreen', 'gored', 'tekkon', 'temple', 'comehome'];
var random = sets[Math.round(Math.random() * (sets.length - 1))];
return {
    set: function () {
        random = sets[Math.round(Math.random() * (sets.length - 1))];
    },
    take: function (){
        return random
    },
    $get: function () {
        console.log("$get: " + random);
        return {
            random
        };
    }
};
});
我将使用这种形式的设置,稍后将其注入到我的配置中,如下所示。注意:我使用的是UI路由器

$stateProvider
    .state('root', {
        url : "/{name}",
        views: {
            "canvasContainer": {
                templateUrl: function (stateParams) {
                    if (angular.isDefined(stateParams.name) && stateParams.name !== 'p' && stateParams.name !== '') {
                        return 'templates/canvas/cnv.' + stateParams.name + '.html';
                    } else {
                        setsProvider.set();
                        console.log("config: " + setsProvider.$get().random);
                        return 'templates/canvas/cnv.'+setsProvider.$get().random+'.html';
                    }

                },
                controller: 'canvasController'
            }
        }
    })
我有一个函数可以重新加载当前状态

$scope.refresh = function (){
    $state.reload();
};
在另一个控制器中,我有一个$watch检测来自我的提供商的set.random上的更改。但是,未正确检测到更改

$scope.set= sets.random;
$scope.$watch(
    function(scope) {
        return sets.random;
    },
    function(newValue, oldValue) {
        console.log("New value is: " + sets.random);
        $scope.set = newValue;
    }
    );
这是我在控制台中得到的输出:

$get: gored
$get: gogreen
config: gogreen
$get: gogreen
$watch: gored
refresh(): gored
$get: temple
config: temple
$get: temple
$watch: gored
refresh(): gored
$get: tekkon
config: tekkon
$get: tekkon
$watch: gored
refresh(): gored
$get: tekkon
config: tekkon
$get: tekkon
$watch: gored
refresh(): gored
$get: gored
config: gored
$get: gored
$watch: gored
refresh()和$watch位于两个不同的控制器中,但它们不断释放相同的旧值。所以我的假设是控制器不能跟踪随机变量。我对这一切都很陌生,任何帮助都将不胜感激

另外,我的控制器设置如下:

app.controller('canvasController', ['sets',  function(sets){
//-----Code----
}]);

正如Mathew所提到的,使用$broadcast可能会有帮助,但是我无法用这个方法得到任何结果,因为它不断地向我抛出不同的错误。但我最终还是能够通过修改代码来实现这一点,而解决方案实际上非常简单

我修改了我的提供者,如下所示:

app.provider('sets', function (){
    var sets= ['gogreen', 'gored', 'tekkon', 'temple', 'comehome'];
    var random;
    return {
        set: function () {
            random = sets[Math.round(Math.random() * (sets.length - 1))];
        },
        $get: function () {
            // console.log("$get: " + random);
            return {
                'random' : random,
                set : function () {
                    random = sets[Math.round(Math.random() * (sets.length - 1))];
                    return random;
                },
                get : function () {
                    return random;
                }
            };
        }
    };
});
$scope.refresh = function (){
    sets.set();
    $state.reload();
};
stateProvider仍如上述问题所示。 refresh()函数修改如下:

app.provider('sets', function (){
    var sets= ['gogreen', 'gored', 'tekkon', 'temple', 'comehome'];
    var random;
    return {
        set: function () {
            random = sets[Math.round(Math.random() * (sets.length - 1))];
        },
        $get: function () {
            // console.log("$get: " + random);
            return {
                'random' : random,
                set : function () {
                    random = sets[Math.round(Math.random() * (sets.length - 1))];
                    return random;
                },
                get : function () {
                    return random;
                }
            };
        }
    };
});
$scope.refresh = function (){
    sets.set();
    $state.reload();
};
最后,我甚至不需要$watch或$broadcast。值在提供程序中更改时在控制器中动态更新

我通过遵循某些逻辑和模式找到了这个解决方案,但不知道为什么它会起作用。对于直接从$get检索的对象在控制器中不会自动更新,但如果从$get内的函数检索,则会自动更新的原因,请给出任何解释。基本上,这两者之间的区别是:

set: function () {
            random = sets[Math.round(Math.random() * (sets.length - 1))];
        },
$get: function () {
        console.log("$get: " + random);
        return {
            random
        };
    }
这是:

set: function () {
            random = sets[Math.round(Math.random() * (sets.length - 1))];
        },
$get: function () {
            // console.log("$get: " + random);
            return {
                'random' : random,
                set : function () {
                    random = sets[Math.round(Math.random() * (sets.length - 1))];
                    return random;
                },
                get : function () {
                    return random;
                }
            };
        }

谢谢

提供者返回的服务对象需要在rootScope上广播该值已更改,然后控制器可以侦听该事件。在作用域上使用观察者是行不通的,因为只有当作用域的父级发生变化时,才会对其进行消化。因为服务可以在没有任何范围更改的情况下进行更新。“守望者”不会开火。@MathewFoscarini你能再详细一点吗?我尝试在get方法中使用$rootScope.$broadcast,但此后整个应用程序停止运行。不会抛出任何错误。也尝试了$injector,但得到了相同的结果。先谢谢你