Question

An AngularJS app depend on the $injector service to inject other built-in or customize services in controller,directive or other injectable things, but how $injector service inject itself,just like :

app.controller(function($injector,$scope){

//...

});
Était-ce utile?

La solution

Debugging into angular's source code, whenever angular compiles an element having ng-controller, it calls this function to instantiate the controller and injects all dependencies:

controllerInstance = $controller(controller, locals);

Inside the $controller method, it calls this method

instance = $injector.instantiate(expression, locals);

to instantiate the controller based on the expression, in your case is function ($injector,$scope){}:

Which in turn calls invoke, notice this code snippet:

for(i = 0, length = $inject.length; i < length; i++) {
        key = $inject[i];
        if (typeof key !== 'string') {
          throw $injectorMinErr('itkn',
                  'Incorrect injection token! Expected service name as string, got {0}', key);
        }
        args.push(
          locals && locals.hasOwnProperty(key)
          ? locals[key]
          : getService(key)
        );
      }

This loop is to create all dependencies and store in the args array. For each loop, it checks for locals first (containing something like $scope,$element,$attr for the current element). The important function call to notice is the getService(key):

function getService(serviceName) {
      if (cache.hasOwnProperty(serviceName)) {
        if (cache[serviceName] === INSTANTIATING) {
          throw $injectorMinErr('cdep', 'Circular dependency found: {0}', path.join(' <- '));
        }
        return cache[serviceName]; //angular run to this line for $injector service
      } else {
        try {
          path.unshift(serviceName);
          cache[serviceName] = INSTANTIATING;
          return cache[serviceName] = factory(serviceName);
        } catch (err) {
          if (cache[serviceName] === INSTANTIATING) {
            delete cache[serviceName];
          }
          throw err;
        } finally {
          path.shift();
        }
      }
    }

In case of $injector service, when angular initializes the module, it creates an $injector and store in this cache.

This means that $injector does not inject itself, $injector is just another service in this service cache. Whenever angular needs to inject a service, angular will look in this cache, if the service does not exist, angular will create it. $injector is one of the first services in this cache

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top