2016-06-28 23 views
2

我在使自定义角度服务工作时遇到问题。在控制器从服务异步获取/设置数据之间共享数据 - AngularJS

我的服务如下:

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 [] 

}); 

编辑 我的一些代码是模糊的,加了我的路线部分,应该是一个更加清楚一点。我忘记了,如果我在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 
    }) 
+0

您的代码中有语法错误。你确定在AJAX请求完成后第二个控制器正在请求数据吗?请分享显示控制器何时初始化的[mcve]。 –

+1

'console.log'将在控制器创建时执行,并且只有一次,当您的应用程序运行时。那时你在阵列中没有任何东西。你的应用可能没问题,但你只是没有正确访问阵列。 –

+0

嗯,我使用角度路由,但这并不意味着第二个控制器稍后实例化? – intrinsiciwnl

回答

0

也许是因为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); 

}); 
+0

没有3是正确的方法来做到这一点... –

+0

这取决于。在非常大的网络应用程序中,为了缩短$摘要循环并保持应用程序的快速,不鼓励观看所有内容。这里最常见的做法是观察从控制器到服务的变化,或者使用'$ broadcast' /'$ emit'实现信号系统。 – morels

+0

我说没有3,它正在实现承诺。 –

0

为我的项目,我通常把我的$http S在各自的服务,如果需要进行外调用暴露功能。

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承诺,以便在控制器端显示成功或错误。

相关问题