Maison >interface Web >js tutoriel >Une brève analyse du cycle de vie et du traitement différé dans AngularJS_AngularJS
Nous discutons ici de certains conteneurs d'inversion de contrôle avancés couramment utilisés : chargement différé, gestion de la durée de vie et résolution de création/traitement différé).
Chargement paresseux
Le chargement dit paresseux consiste à instancier l'objet lorsque vous avez besoin de l'utiliser. De nombreux systèmes d’injection de dépendances créent dès le début des composants en tant que dépendances. Mais parfois, vous ne souhaitez pas instancier ces composants tant que vous ne les utilisez pas dans votre application. Dans Angular, un bon exemple est lorsque vous définissez un comportement lors de la configuration et que le comportement fait référence à certains composants qui n'ont pas encore été créés.
Supposons que vous souhaitiez intercepter le service $log intégré au système, vous le stockez donc dans $rootScope. Bien sûr, je ne le recommande pas, mais cet exemple est plus simple et plus efficace. Pour intercepter, vous utilisez $provide lors de la configuration, puis appelez la méthode modifiée. Si vous souhaitez référencer directement $rootScope à ce moment-là, vous obtiendrez une exception due à une référence circulaire. Et la solution consiste à charger paresseux $rootScope via $injector .
Le code suivant ne chargera $rootScope que lors de sa première utilisation.
$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; }]);
Les appels suivants obtiendront le même singleton $rootScope. Voici un exemple fonctionnel. Il me semble avoir déjà entendu une déclaration (incorrecte) (Angular ne prend en charge que les singletons)... Bien sûr, ce n'est pas vrai. Les méthodes de $injector sont utilisées pour gérer pour vous le cycle de vie de vos composants.
Gestion du cycle de vie
Le cycle de vie implique la façon dont vous gérez les instances de composants. Par défaut, lorsque vous injectez une dépendance angulaire, Dependency Injection en créera une copie pour vous et la réutilisera dans votre application. La plupart du temps, c’est exactement ce à quoi nous nous attendons. Dans certains cas, plusieurs instances du même composant sont requises. Supposons le service de comptage suivant :
Counter($log) { $log.log(); } angular.extend(Counter.prototype, { count: 0, increment: () { .count += 1; .count; } }); Counter.$inject = []; app.service(, Counter);
Votre application gardera une trace des différents compteurs. Et après avoir injecté le service, vous obtiendrez toujours le même compteur. Est-ce une limitation d'Angular ?
Bien sûr que non. Encore une fois, vous pouvez créer une nouvelle copie à tout moment via le service $injector. Le code suivant utilise deux compteurs indépendants :
app.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; }; }; }]);
Vous pouvez voir que les compteurs sont suivis par des instances distinctes, voici un exemple utilisable. Si vous devez générer fréquemment de nouvelles instances, vous pouvez enregistrer le service comme ceci :
app.factory(, [, (i) { { getCounter: () { i.instantiate(Counter); } }; }]);
C'est aussi simple que cela de générer l'instance requise, et vous pouvez utiliser votre composant d'usine à la place $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(); }; }]);
Vous pouvez consulter cette version complète de l'exemple disponible. Comme vous pouvez le constater, il est tout à fait possible de gérer le cycle de vie de vos composants à l'aide de l'injection de dépendances intégrée d'Angular. Qu'en est-il de la résolution différée : par exemple, vous devez importer des composants après la configuration d'Angular et les encapsuler avec leurs dépendances.
Résolution différée
Nous avons introduit un moyen de gérer paresseusement les dépendances dans Angular. Lorsque vous souhaitez envelopper quelque chose, vous pouvez appeler l'instanciation du service $injector, et il peut ensuite résoudre la dépendance en reniflant les paramètres, ce qui semble utiliser les propriétés statiques de $inject, ou il peut également le faire en inspectant le Il est implémenté sous forme de tableau. En d’autres termes, ce qui suit est une manière d’écrire tout à fait valable :
$injector.instantiate(['dependency', Constructor]);
Vous pouvez également appeler des méthodes sur des tableaux décorés. Supposons que vous ayez une méthode qui dépend du service $log. Vous pouvez l'appeler au moment de l'exécution avec un traitement différé, comme ceci :
myFunc = [, ($log) { $log.log(); }]; $injector.invoke(myFunc);
Vous pouvez jeter un œil à cet exemple fonctionnel (ouvrez votre console et voyez ce qui se passe après avoir appuyé sur le bouton).
Résumé
Pour résumer, l'injection de dépendances d'Angular fournit de nombreuses fonctionnalités avancées que vous souhaiterez et que vous utiliserez souvent dans la chaîne de production de vos applications métier. La commodité des usines, des services et des fournisseurs amène souvent les développeurs Angular à croire qu'il n'y a qu'une seule option disponible. La magie réside dans le service $injector, que vous pouvez utiliser pour générer les singletons requis, créer de nouveaux composants ou référencer dynamiquement des méthodes avec des dépendances.
Enfin, notez que les injections dans votre code client sont disponibles même en dehors d'Angular. Regardons un exemple d'appel du service $log par injection, encapsulé en dehors d'Angular, cliquez ici. Pourquoi devons-nous passer « ng » dans le tableau de la méthode ? Il s'agit d'un module principal d'Angular et sera ajouté implicitement lorsque vous envelopperez votre module, mais si votre directive génère sa propre instance injectée, vous devez l'ajouter explicitement.