Angular service delays sending messages Lazy-Loading, $timeout service

Delayed message sending and $timeout service

Here, we discuss some common advanced Inversion of Control containers: lazy-loading, lifetime management, and deferred creation/resolution.
 
Lazy-Loading

The so-called lazy loading is to instantiate the object when you need it. Many dependency injection systems start by creating components as their dependencies. But sometimes, you don't want to instantiate these components until you use them in your application. In Angular, a good example is when you set a behavior during configuration, and the behavior will refer to some components that have not yet been created.

Suppose you want to intercept the system's built-in $log service, so you store it in $rootScope. Of course, I don't recommend doing this, but this example is simpler and more effective. In order to intercept, you use $provide when configuring and then call the decoration method. If you try to reference $rootScope directly at this point, you will get an exception due to a circular reference. The solution is to lazy load $rootScope via $injector.


The following code will only load $rootScope the first time it is used.

$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;
}]);

Subsequent calls will get the same singleton $rootScope. Here is an example available . I seem to have heard a (wrong) statement before (Angular only supports singletons)...

Of course not. The methods in $injector are used to manage the lifecycle of your components for you.

life cycle management

Lifecycle involves how you manage instances of components. By default, when you inject an Angular dependency, dependency injection will create a copy of it for you and then in

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

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 的核心模块,

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





Guess you like

Origin blog.csdn.net/qq_40071033/article/details/78334169