Angular手表出厂值

Angular watch factory value

假设我有以下工厂:

app.factory("categoryFactory", function (api, $http, $q) {    
    var selected = null;
    var categoryList = [];
    return {
        getList: function () {
            var d = $q.defer();
            if(categoryList.length  <= 0){
                $http.get(api.getUrl('categoryStructure', null))
                    .success(function (response) {
                        categoryList = response;
                        d.resolve(categoryList);
                    });
            }
            else
            {
                d.resolve(categoryList)
            }
            return d.promise;
        },
        setSelected: function (category) {
            selected = category;
        },
        getSelected: function () {
            return selected;
        }
    }    
});

现在我有两个控制器同时使用这个工厂。因此,为此更新时必须通知两个控制器,我尝试了以下操作:

    app.controller('DashboardController', ['$http', '$scope', '$sessionStorage', '$log', 'Session', 'api','categoryFactory', function ($http, $scope, $sessionStorage, $log, Session, api, categoryFactory) {

    $scope.selectedCategory = categoryFactory.getSelected();

}]);

虽然我的另一个控制器看起来像这样:

    app.controller('NavController', ['$http', '$scope', '$sessionStorage', '$log', 'Session', 'api', 'FileUploader', 'categoryFactory', function ($http, $scope, $sessionStorage, $log, Session, api, FileUploader, categoryFactory) {
    $scope.categories = [];

    categoryFactory.getList().then(function (response) {
        $scope.categories = response;
    });
    $scope.selectCategory = function (category) {
        categoryFactory.setSelected(category);
    }

}]);

如何在 NavController 更改值时在 DashboardController

中没有更改

我的问题是我如何 watch 或以其他方式在值更改时收到通知?

您可以使用 observer 模式,如下所示:

app.factory("categoryFactory", function (api, $http, $q) {   
    // the list of callbacks to call when something changes
    var observerCallbacks = []; 

    // ...

    function notifyObservers() {
        angular.forEach(observerCallbacks, function(callback) {
            callback();
        });
    }

    return {
        setSelected: function (category) {
            selected = category;
            // notify the observers after you change the value
            notifyObservers();
        },
        registerObserver: function(callback) {
            observerCallbacks.push(callback);
        }
    }    
});

然后在您的控制器中:

app.controller('NavController', ['$http', '$scope', '$sessionStorage', '$log', 'Session', 'api', 'FileUploader', 'categoryFactory', function ($http, $scope, $sessionStorage, $log, Session, api, FileUploader, categoryFactory) {
    // ...

    // init
    (function() {
        categoryFactory.registerObserver(function() {
            categoryFactory.getList().then(function (response) {
                $scope.categories = response;
            });
        });
    })();

}]);

这样,任何时候调用 setSelected,它都会调用您在 observerCallbacks 中注册的每个回调。您可以从任何控制器注册这些,因为工厂是单身人士,他们将始终知情。

编辑: 只是想补充一点,我可能把 notifyObservers() 调用放在了错误的区域(目前在 setSelected),我可能在控制器中放置错误的更新调用(当前 getList),但架构保持不变。在 registerObserver 中,将值更新时您想做的任何事情以及您希望观察者知道的任何更改都放在调用 notifyObservers()

您可以在此处关注 dot rule,以便遵循原型继承。

基本上你需要在你的服务中有一个对象,它将有 selected 变量,并且会摆脱 getSelected 方法。

工厂

app.factory("categoryFactory", function(api, $http, $q) {
    var categoryFactory = {};
    categoryFactory.getList = function() {
        var d = $q.defer();
        if (categoryList.length <= 0) {
            $http.get(api.getUrl('categoryStructure', null))
                .success(function(response) {
                    categoryList = response;
                    d.resolve(categoryList);
                });
        } else {
            d.resolve(categoryList)
        }
        return d.promise;
    }
    categoryFactory.setSelected = function(category) {
        categoryFactory.data.selected = category;
    }
    categoryFactory.data = {
        selected: null
    }
    return categoryFactory;
});

控制器

app.controller('DashboardController', ['$http', '$scope', '$sessionStorage', '$log', 'Session', 'api', 'categoryFactory',
    function($http, $scope, $sessionStorage, $log, Session, api, categoryFactory) {
        //this will provide you binding without watcher
        $scope.selection = categoryFactory.data;
    }
]);

然后在 html 部分使用 {{selection.selected}} 将在选择发生变化时更新值。