angular服务延迟发送消息延迟加载(Lazy-Loading),$timeout服务

延迟消息发送还有$timeout服务

这里,我们再讨论一些常用的高级的控制反转容器(Inversion of Control containers):延迟加载(lazy-loading),生命周期管理(lifetime management),以及延迟的创建/处理(deferred creation/resolution)。
 
延迟加载(Lazy-Loading)

所谓延迟加载就是当你需要用到对象时候才对其进行实例化。许多依赖注入系统都会在一开始就创建组件,作为它的可依赖项目。不过有时候,直到在应用中用到它们之前,你都不会想去实例化这些组件。Angular 中,一个很好的例子就是,当你在配置的时候去设置一个行为,而该行为又会引用到一些还没创建的组件。

假设你想拦截系统内建的 $log 服务,因此你把它存在了 $rootScope 里面。当然我不建议这样做,不过这样举例比较简单有效。为了拦截,你在配置的时候用到了 $provide 然后调用修饰方法。如果这时你想直接引用 $rootScope 的话,由于循环引用你会拿到个异常。而解决案是通过 $injector 延迟加载 $rootScope 。


下面的代码只会在 $rootScope 第一次被使用的时候才去加载它。

$provide.decorator(, [, ,
    ($delegate, $injector) {
      log = $delegate.log.bind($delegate);
     $delegate.log = (msg) {
        rs = $injector.get();
        (rs.logs === undefined) {
         rs.logs = [];
       }
       rs.logs.push(msg);
       log(msg);
     };
      $delegate;
}]);

之后的调用都会拿到一样的单例 $rootScope。 这里有个可用例子。我之前好像听过有个(不对的)说法(Angular 只支持单例) …

当然不是真的。$injector 中的方法就是用来给你管理你的组件的生命周期的。

生命周期管理

生命周期涉及到你如何管理组件的实例。默认情况,当你注入一个 Angular 的依赖,依赖注入就会帮你创建它的一个副本然后在

你的应用里面重用它。大多数情况下这确实是我们所期待的。而有些情况下,会要求同一组件的多个实例。假设下面的计数服务:

Counter($log) {
   $log.log();
}
  
angular.extend(Counter.prototype, {
   count: 0,
   increment: () {
     .count += 1;
      .count;
   }
});
  
Counter.$inject = [];
  
app.service(, Counter);

你的应用要跟踪不同的计数器。而你注入该服务后,总会拿到一样的计数器。这难道是 Angular 的限制?

当然不是。重复一次,通过 $injector 服务你可以在任何时候创建一个新副本。下面的代码用了两个独立的计数器:

pp.run([, , ,
    (rs, c, i) {
     rs.count = c.count;
     rs.update = c.increment;
     rs.update2 = () {
        c = i.instantiate(Counter);
       rs.count2 = c.count;
       rs.update2 = () {
         c.increment();
         rs.count2 = c.count;
       };
     };
   }]);
你可以看到计数器都是被独立的实例跟踪的,这里是 可用例子 。如果你需要经常生成新实例,你可以像这样注册服务:

app.factory(, [,
    (i) {
      {
       getCounter: () {
          i.instantiate(Counter);
       }
     };
   }]);
产生一个需要的实例就是那么简单,而且你可以用你的工厂组件来代替 $injector:

app.run([, ,
    (rs, cf) {
      c1 = cf.getCounter(),
       c2 = cf.getCounter();
     rs.count = c1.count;
     rs.update = c1.increment;
     rs.count2 = c2.count;
     rs.update2 = () {
       rs.count2 = c2.increment();
     };
   }]);

你可以看看这个完整版本的可用例子。如你所见,用 Angular 的内建依赖注入是完全有可能管理你组件的生命周期的。

那延迟处理(deferred resolution)又怎样呢 – 比如说,有些组件你需要在 Angular 已经配置好之后引入,而且需要用它们的依赖来包装起来。

延迟处理(Deferred Resolution)

我们已经介绍了在 Angular 中可以延迟处理依赖的一种方法。当你想包装某些东西的时候,你可以调用 $injector 服务的 instantiate ,

然后它可以通过参数嗅探来解决依赖,看起来就像用 $inject 的静态属性一样,或者也可以通过检查你传给它的数组来实现的。也就是说,

下面这个是完全有效写法:

$injector.instantiate(['dependency', Constructor]);

你还可以调用带装饰数组的方法。假设你有一个方法依赖于 $log 服务,你可以运行时通过延迟处理来调用它,像下面这样:

myFunc = [, ($log) {
   $log.log();
}];
$injector.invoke(myFunc);

你可以看看这个可用例子(打开你的控制台,看看你按下按钮之后发生了什么)。
 head部分

<script src="angular.js"></script>

    <script>
        var app = angular.module("myApp",[]);
        app.controller("myCtrl",function ($scope,$timeout) {
            $scope.width01 = "";
            $scope.heigh02 = "";
            $scope.title01 = "";
            $scope.zjname = "";
            $scope.dkh = "";
            $scope.urlIP = "";
            $scope.end = "";
            $timeout(function () {
                $scope.width01 = "2100px";
                $scope.heigh02 = "700px";
                $timeout(function () {
                    $scope.title01 = "日考11";
                    $scope.zjname = "Lonely";
                    $timeout(function () {
                        $scope.dkh = "172.18.43.28";
                        $scope.urlIP = "http://localhost:63342/WebStorp/lihanxiang1509d20171014.html?_ijt=23iovsjtuoapd00t3qgdt4c2fk";
                        $timeout(function () {
                            $scope.end = "完美 , PerFect";
                        },5000);
                    },2000);
                },1000);
            },2000);
        });
    </script>

body部分


    

我是宽: { {width01}}

我是高: { {heigh02}}

我是标题: { {title01}}

我是主机名: { {zjname}}

我是端口号: { {dkh}}

我是url地址: { {urlIP}}

{ {end}}



总结

综上所述,Angular 的依赖注入提供了许多高级特性,你在商业应用生产线上会希望并且经常会用到它们。

factories, services, 和 providers 的便捷让 Angular 开发者常常产生错觉,认为这里只有唯一选项可用。而神奇之处在于 $injector 服务,

你可以用它生成所需的单例,创建新的组件或者动态引用带依赖的方法。

最后要注意的是,你客户端代码里面的注入即使在 Angular 之外也是可用的。我们来看一个在 Angular 之外包装的,

通过注入调用 $log 服务的例子,点这里。为什么要把 ‘ng' 传入方法的数组?它是 Angular 的核心模块,

当你包装你的模块的时候是会被隐式添加的,但是如果你的指令要生成自己的注入实例的时候,你就必须显式添加了。





猜你喜欢

转载自blog.csdn.net/qq_40071033/article/details/78334169