【问题标题】:share data between controllers getting/setting data asynchronously from a service - AngularJS从服务异步获取/设置数据的控制器之间共享数据 - AngularJS
【发布时间】:2016-10-30 08:25:00
【问题描述】:

我无法让我的自定义角度服务正常工作。

我的服务如下:

app.service('userService', function(){
  var user = [];

  var setUser = function(newObj){
    user.push(newObj);
  };

  var getUser = function(){
    return user;
  };

  return {
    setUser: setUser,
    getUser: getUser
  };
});

app.config(function($routeProvider,$locationProvider) {

  $routeProvider
    .when('/', {
      templateUrl : 'views/home.html',
      controller  : 'indexController'
    })
    .when('/me.html', {
      templateUrl : 'views/me.html',
      controller  : 'meController'
    });

    // Get rid of the additional default pound sign during routing
    $locationProvider.html5Mode(true);
});

我这样称呼它

app.controller('indexController', function($http,userService) {  
                                ...
    $http.post("somewhere")
        .then(function(response){
           userService.setUser({test: "test});
           location="/me.html";
        }
        .then(function(response){
           userService.setUser({test: "test});
           location="/me.html";
        })
});

当我在另一个控制器中执行 console.log 时,它返回一个空数组。我在搞砸什么?

app.controller('meController',function($http,userService){
   console.log(userService.getUser()); => returns an empty array []

});

编辑 我的一些代码很模糊,添加了我的路线部分,应该更清楚一点。 编辑 2 忘了提一下,如果我在 setUser() 之后的行中插入 console.log(userService.getUser()),它会正确显示数据。

$http.post("somewhere")
    .then(function(response){
       userService.setUser({test: "test});
       location="/me.html";
    }
    .then(function(response){
       userService.setUser({test: "test});
       location="/me.html";
       console.log(userService.getUser()); => correct output
    })

【问题讨论】:

  • 您的代码中有语法错误。你确定第二个控制器在 AJAX 请求完成后请求数据吗?请分享 minimal reproducible example 显示控制器何时初始化。
  • console.log 将在创建控制器时执行,并且只有一次,当您的应用程序运行时。那时你在数组中没有任何东西。您的应用程序可能没问题,但您只是没有正确访问数组。
  • 嗯,虽然我使用的是角度路由,但这是否意味着稍后会实例化第二个控制器?
  • @TimHobbs "当控制器被创建时,并且只有一次,当你的应用运行时" - 没有。控制器以 on demand 方式进行初始化。如果在切换到不同的路由时需要第二个控制器(可能在 AJAX 请求之后),它将在那时初始化。
  • @intrinsiciwnl 阅读了我上面的评论。正如我在之前的评论中提到的,在minimal reproducible example 中显示控制器是如何初始化的。

标签: angularjs angularjs-scope angularjs-controller


【解决方案1】:

可能是因为 console.log 指令在从另一个控制器取消分配之前运行。

您可以通过以下方式修复它:

  1. 实现回调系统
  2. $scope.watching service.getUser()
  3. 在服务中实现承诺
  4. $broadcast/$emit实现一个信号系统

对于案例 1,您可以这样做:

app.service('userService', function(){
  var user = [],callbacks = [];

  var setUser = function(newObj){
    user.push(newObj);
    for(var i = 0;i< callbacks.length;++i)
      callbacks[i](user);
  };

  var getUser = function(){
    return user;
  };

  var onUserChange = function(callback) {
    callbacks.push(callback);
  };

  return {      
    onUserChange:onUserChange,
    setUser: setUser,
    getUser: getUser
  };
});

并尝试在您的第二个控制器中调用它。

对于案例 2。

app.controller('meController',function($http,$scope,userService){
  $scope.$watch(function(){ return userService.getUser(); },
                function(newvalue){ console.log(newvalue); },
                true);

});

【讨论】:

  • 视情况而定。在非常大的 Web 应用程序中,不鼓励查看所有内容以缩短 $digest 周期并保持应用程序快速运行。这里最常见的做法是观察从控制器到服务的变化或使用$broadcast/$emit 实现信号系统
  • 我说没有 3,这是在执行承诺。
  • 您的方法仍在打印一个空数组。
  • 1.什么方法? 2. 有没有你没有提供的控制台信息?
  • 第一种方法打印一个没有值但从我认为的默认对象继承的值的对象。第二个只是打印一个空数组。
【解决方案2】:

对于我的项目,我通常将我所有的$https 放在各自的服务中,并在需要在外部调用时公开函数。

app.service('userService', function(){
  var user = [];
  var isReady = false;

  var setUser = function(newObj){
    user.push(newObj);

    $http(...).then(function(){}, failHandler);

    function failHandler() {
      // undo the push and show error to user
    }
  };

  var getUser = function(){
    if (isReady) {
      return $q.when(user);
    }
    else {
      return $http(...).then(function(data){
        user = data.xxx;
        isReady = true;
      });
    }
  };

  return {
    setUser: setUser,
    getUser: getUser
  };
});

请注意,getUser 现在正在返回一个承诺,因此您需要使用 .then 来处理事情。

您也可以将setUser 更改为promise,以便在控制器端显示成功或错误。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-12-15
    • 2014-03-22
    • 1970-01-01
    • 2013-05-28
    • 2013-02-25
    • 2014-12-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多