AngularJS在控制器之间共享异步数据

AngularJS sharing async data between controllers

本文关键字:异步 数据 共享 之间 控制器 AngularJS      更新时间:2023-09-26
有很多

主题涵盖了在控制器之间共享数据的问题,但我没有找到任何好的答案。

我有一个控制器可以使用 promise 异步获取数据。然后,控制器创建要在该范围内使用的数据的副本。然后我有第二个控制器,我还想处理与第一个控制器相同的数据副本,以便它们都共享它。

下面是一些简化的代码作为示例:

.controller('firstController', function ($scope, someService){
    var vm = this;
    someService.getData().then(function(data) {
        angular.copy(data, vm.data); //creates a copy and places it on scope
        someService.setCurrentData(vm.data)
    }
});
.controller('secondController', function ($scope, someService){
    var vm = this;
    vm.data = someService.getCurrentData(); //Triggers before the setter in firstController
});
.factory('someService', function(fetchService){
    var _currentData = {};
    var getData = function(){
        return fetchService.fetchData().then(function(data) { return data; });
    };
    var getCurrentData = function(){
        return _currentData;
    }
    var setCurrentData = function(data){
        _currentData = data;
    }
});

由于getData是异步的,因此setCurrentData将在getCurrentData之后触发,因此getCurrentData给出了一个不同的对象,并且不会更改为正确的对象。我知道你可以通过广播和观看来解决这个问题,但如果可能的话,我尽量避免使用它。

重构工厂以检查是否已设置_currentData变量 - 然后您可以简单地使用回调:

app.factory('someService', function(fetchService){
    var _currentData = null;
    var setCurrentData = function(data){
        _currentData = data;
    }
    var getData = function(callback) {
        if (_currentData == null) {
            fetchService.fetchData().success(function(data) { 
                setCurrentData(data);
                callback(data); 
            });
        } else {
            callback(_currentData);
        }
    };
    /*
    var getCurrentData = function(){
        return _currentData;
    }
    */
});

现在,调用您的getData服务将检查数据是否已获取并存储,如果是,请使用它,否则去获取它!

someService.getData(function(data) {
    console.log(data); //yay for persistence!
})

我会这样解决:

.controller('firstController', function ($scope, $rootScope, someService){
    var vm = this;
    someService.getData().then(function(data) {
        angular.copy(data, vm.data); //creates a copy and places it on scope
        someService.setCurrentData(vm.data);
        $rootScope.$broadcast('myData:updated');
    }
});

.controller('secondController', function ($scope, $rootScope, someService){
        var vm = this;
        $rootScope.$on('myData:updated', function(event, data) {
           vm.data = someService.getCurrentData(); 
        });
});