angular系列彻底的异步解决

Angular 的异步处理的真的很不错。基于消息广播的方式,并且可以向上传递,基本上解决了不同模块,不同controller之间不方便异步的问题。

场景一:通过回调函数进行异步操作(该情况下不用消息广播的机制)

这种情况的特点是直接传递一个回调函数给异步操作就可以了,等异步操作完执行回调。

比如:controller通过server异步取数据,等取完数据进行一系列的操作,这个时候就可以把操作封装到函数中,传递给异步操作函数。

controller代码片段举例如下:

[javascript]view plaincopy

  1. $scope.submit=function(){
  2. userService.login($scope.user.loginname.value,$scope.user.password.value,function(data){
  3. if(data.success){
  4. location.href = '../../views/main/index.html';
  5. }else{
  6. $scope.user.error.tip=data.msg;
  7. }
  8. });
  9. };

最后一个参数即为回调函数

server代码片段举例如下:

[javascript]view plaincopy

  1. return {
  2. http:$http,
  3. token:'',
  4. auth:[],
  5. loginname:'',
  6. login:function(loginname,password,fn){
  7. this.http({
  8. url:'../../scripts/loginModule/services/loginOKTest.js',
  9. method:'GET'
  10. })
  11. .success(function(data){
  12. if(data[0].success){
  13. ...
  14. //调用回调方法
  15. fn(data[0]);
  16. }
  17. })
  18. .error(function(data,header,config,status){
  19. alert("验证服务请求失败!");
  20. });
  21. }
  22. }

场景二:没有传递回调函数的地方,这个时候就必须用到消息广播的机制。

比如:我的controller通过server异步获取数据,这个时候我用回调函数保证取到数据后做后续操作。但是我的后续操作需要通过指令进行DOM的生成。这个时候我们是没有办法直接调用指令的link或者compile的。这个时候我们需要用到广播$scope.$broadcast。发送广播以后,需要通过$scope.$on进行监听。

controller代码片段举例如下:

[javascript]view plaincopy

  1. //通过categoryService异步取数据
  2. categoryService.initCategory(loginname,token,function(category){
  3. $scope.category=category;
  4. $scope.$broadcast("categoryLoaded");
  5. });

service代码片段举例如下:

[javascript]view plaincopy

  1. initCategory:function(loginname,token,fn){
  2. this.http({
  3. url:'../../scripts/mainModule/services/mainCategory.js',
  4. method:'GET'
  5. }).success(function(data,header,config,status){
  6. fn(data);
  7. }).error(function(data,header,config,status){
  8. alert("验证服务请求失败!");
  9. });
  10. }

directive代码片段举例如下:

[javascript]view plaincopy

  1. link:function ($scope, $elem, attrs) {
  2. $scope.$on("categoryLoaded", function (event, args) {
  3. //$scope.category即为异步获取的数据
  4. }
  5. }

最后,如果我们在这个controller中需要调用另外一个模块的指令的link或者compile或者另一个模块的controller怎么办。我们需要通过依赖注入$rootScope服务,因为他是所有作用域的父,然后调用$emit这个服务进行广播。指令中通过$rootScope.$on进行接收即可。

模块1(app.video)中的controller代码片段举例如下:

[javascript]view plaincopy

  1. $scope.replay=function(id){
  2. console.log("click replay id:"+id);
  3. clearReply();
  4. //通过$rootScope广播消息给app.dialog模块的controller
  5. $rootScope.$emit("openTemplate","reply.html");
  6. };

模块2(app.dialog)中的controller代码片段举例如下:

[javascript]view plaincopy

    1. $rootScope.$on('openTemplate',function(event, toState, toParams, fromState, fromParams){
    2. $scope.openTemplate(toState);
    3. });
    4. $scope.openTemplate = function (url) {
    5. if(!url)
    6. url="/ZVideo-MVC/dialog/defaultTemplate.html";
    7. $scope.value = true;
    8. ngDialog.open({
    9. template: url,
    10. className: 'ngdialog-theme-plain',
    11. scope: $scope
    12. });
    13. };