ServiceScope class
Modèle de localisateur de service utilisé par le SharePoint Framework.
Remarques
ServiceScope fournit un moyen formalisé pour les composants d’inscrire et de consommer des dépendances (« services ») et de permettre l’inscription de différentes implémentations dans différentes étendues. Cela améliore la modularité en découpant les composants de leurs dépendances de manière extensible.
Par exemple, supposons que différents composants doivent accéder à un instance IPageManager. Nous pourrions simplement faire du PageManager un singleton (c’est-à-dire une variable globale), mais cela ne fonctionnera pas, par exemple, si nous devons créer une boîte de dialogue contextuelle qui nécessite une deuxième instance PageManager. Une meilleure solution consiste à ajouter le PageManager en tant que paramètre de constructeur pour chaque composant qui en a besoin. Toutefois, nous sommes immédiatement confrontés au problème que tout code qui appelle ces constructeurs a également besoin d’un paramètre PageManager. Dans une application avec de nombreuses dépendances de ce type, la logique métier qui lie de nombreux sous-systèmes finirait par récupérer un paramètre de constructeur pour chaque dépendance possible, ce qui est maladroit. Une solution naturelle consiste à déplacer toutes les dépendances dans une classe nommée « ApplicationContext », puis à la transmettre en tant que paramètre de constructeur. Cela permet de passer le PageManager aux classes qui en ont besoin sans encombrer les classes intermédiaires qui n’en ont pas. Toutefois, il existe toujours un problème de conception lié au fait que « ApplicationContext » a des dépendances codées en dur sur de nombreux éléments non liés. Une approche plus flexible consiste à en faire un dictionnaire capable de rechercher des éléments pour les consommateurs/fournisseurs qui connaissent la clé de recherche appropriée (par exemple, ServiceKey). Il s’agit du modèle de conception populaire de « localisateur de services », familier de l’API SPContext dans SharePoint classique.
ServiceScope approfondit cette idée de deux manières importantes : tout d’abord, il fournit un mécanisme d’étendue qui, par exemple, si nous avons deux pages différentes, elles peuvent chacune fournir un instance PageManager unique tout en partageant d’autres dépendances communes. Deuxièmement, elle permet à servicekey de fournir une implémentation par défaut de la dépendance. Ceci est important pour la stabilité de l’API dans notre environnement modulaire côté client : par exemple, supposons que la version 2.0 de notre application introduise une nouvelle interface IDiagnosticTracing qu’un composant de la version 2.0 s’attend à consommer. Si le composant version 2.0 est chargé par une ancienne application 1.0, il échoue. Nous pourrions résoudre ce problème en demandant à chaque consommateur de case activée pour toutes les dépendances manquantes et de gérer ce cas, mais cela nécessiterait de nombreuses vérifications. Une meilleure solution consiste à s’assurer qu’une implémentation par défaut existe toujours, peut-être simplement un comportement trivial, afin que les composants puissent supposer que consume() retourne toujours un objet qui implémente le contrat.
Utilisation : les instances ServiceScope sont créées en appelant ServiceScope.startNewRoot() ou ServiceScope.startNewChild(). Ils sont initialement dans un état « inachevé », pendant lequel provide() peut être appelé pour inscrire des clés de service, mais consume() n’est pas autorisé. Une fois ServiceScope.finish() appelé, consume() est autorisé et provide() est désormais interdit. Ces sémantiques garantissent que ServiceScope.consume() retourne toujours le même résultat pour la même clé et ne dépend pas de l’ordre d’initialisation. Il nous permet également de prendre en charge les dépendances circulaires sans nous soucier des boucles infinies. (Il est préférable d’éviter les dépendances circulaires, mais cela est difficile à garantir lorsque vous travaillez avec des composants qui ont été fournis par divers tiers sans aucune coordination.) Pour éviter les erreurs, il est préférable d’appeler toujours consume() à l’intérieur d’un rappel à partir de serviceScope.whenFinished().
Constructeurs
(constructor)(parent) | Construit une nouvelle instance de la |
Méthodes
consume(service |
Consomme un service à partir de l’étendue du service. |
create |
Il s’agit d’une fonction abrégée qui équivaut à construire une nouvelle instance du simpleServiceClass, puis à l’inscrire en appelant ServiceScope.provide(). |
create |
Il s’agit d’une fonction de raccourci qui construit l’implémentation par défaut du serviceKey spécifié, puis l’enregistre en appelant ServiceScope.provide(). |
finish() | Termine la séquence d’initialisation pour une étendue de service. |
get |
Renvoie le parent du ServiceScope actuel ou « Undefined » s’il s’agit d’une étendue racine. |
provide(service |
Ajouter un nouveau service à une étendue de service. |
start |
Construit un nouveau ServiceScope qui est un enfant de l’étendue actuelle. |
start |
Créez un nouveau ServiceScope de niveau racine. Seules les étendues de niveau racine peuvent créer automatiquement des implémentations par défaut de ServiceKeys. |
when |
Différer une opération jusqu’à ce que ServiceScope.finish() soit terminé. |
Détails du constructeur
(constructor)(parent)
Construit une nouvelle instance de la ServiceScope
classe
protected constructor(parent: ServiceScope | undefined);
Paramètres
- parent
-
ServiceScope | undefined
Détails de la méthode
consume(serviceKey)
Consomme un service à partir de l’étendue du service.
consume<T>(serviceKey: ServiceKey<T>): T;
Paramètres
- serviceKey
-
ServiceKey<T>
clé que vous avez utilisée lorsque provide() a été appelé pour enregistrer le service
Retours
T
l’instance de service
Remarques
Les composants doivent appeler cette fonction pour « consommer » une dépendance, par exemple, rechercher serviceKey et retourner l’instance du service enregistré. Si le instance est introuvable, une instance par défaut est automatiquement créée et inscrite auprès du ServiceScope racine.
createAndProvide(serviceKey, simpleServiceClass)
Il s’agit d’une fonction abrégée qui équivaut à construire une nouvelle instance du simpleServiceClass, puis à l’inscrire en appelant ServiceScope.provide().
createAndProvide<T>(serviceKey: ServiceKey<T>, simpleServiceClass: {
new (serviceScope: ServiceScope): T;
}): T;
Paramètres
- serviceKey
-
ServiceKey<T>
clé pouvant servir ultérieurement pour utiliser le service
- simpleServiceClass
-
{ new (serviceScope: ServiceScope): T; }
classe TypeScript à créer
Retours
T
une instance de simpleServiceClass qui vient d’être créée
createDefaultAndProvide(serviceKey)
Il s’agit d’une fonction de raccourci qui construit l’implémentation par défaut du serviceKey spécifié, puis l’enregistre en appelant ServiceScope.provide().
createDefaultAndProvide<T>(serviceKey: ServiceKey<T>): T;
Paramètres
- serviceKey
-
ServiceKey<T>
clé pouvant servir ultérieurement pour utiliser le service
Retours
T
une instance de service qui a été construite à l’aide de ServiceKey.defaultCreator
finish()
Termine la séquence d’initialisation pour une étendue de service.
finish(): void;
Retours
void
Remarques
Lorsqu’un ServiceScope est démarré pour la première fois, il est dans un état « inachevé » où provide() est autorisé, mais consume() est interdit. Après avoir appelé finish(), consume() est autorisé, mais provide() n’est pas autorisé.
Ce formalisme empêche un certain nombre de situations complexes qui pourraient entraîner des bogues. Par exemple, supposé que Scope2 est un enfant de Scope1, et Scope1 fournit instance A1 de l’interface A. Si quelqu’un consomme A1 à partir d’Scope2 (via l’héritage) avant l’appel de Scope2.provide() avec A2, un appel ultérieur à Scope2.consume() peut retourner un résultat différent de l’appel précédent. Ce non-déterminisme peut entraîner des résultats imprévisibles qui sont difficiles à diagnostiquer.
getParent()
Renvoie le parent du ServiceScope actuel ou « Undefined » s’il s’agit d’une étendue racine.
getParent(): ServiceScope | undefined;
Retours
ServiceScope | undefined
l’étendue du service parent
provide(serviceKey, service)
Ajouter un nouveau service à une étendue de service.
provide<T>(serviceKey: ServiceKey<T>, service: T): T;
Paramètres
- serviceKey
-
ServiceKey<T>
clé qui servira ultérieurement pour utiliser le service
- service
-
T
instance du service en cours d’enregistrement
Retours
T
le même objet qui a été transféré comme paramètre « service »
Remarques
ServiceScope.provide() est utilisé pour inscrire une implémentation de serviceKey donnée pour l’étendue actuelle et une implémentation d’une rootServiceKey donnée pour l’étendue racine. Il peut être utilisé uniquement lorsque le ServiceScope est défini sur l’état « Undefined », c'est-à-dire avant que finish() ait été appelé.
startNewChild()
Construit un nouveau ServiceScope qui est un enfant de l’étendue actuelle.
startNewChild(): ServiceScope;
Retours
le nouveau ServiceScope racine créé
Remarques
Les étendues de service forment une arborescence, de sorte que lors de l’utilisation d’un service, si la clé n’est pas fournie explicitement par une étendue enfant, la hiérarchie parente est consultée.
startNewRoot()
Créez un nouveau ServiceScope de niveau racine. Seules les étendues de niveau racine peuvent créer automatiquement des implémentations par défaut de ServiceKeys.
static startNewRoot(): ServiceScope;
Retours
le nouveau ServiceScope racine créé
whenFinished(callback)
Différer une opération jusqu’à ce que ServiceScope.finish() soit terminé.
whenFinished(callback: () => void): void;
Paramètres
- callback
-
() => void
Bloc de code qui doit appeler ServiceScope.consume()
Retours
void
Remarques
L’appel de ServiceScope.consume() avant l’appel de finish() est une erreur. La façon la plus fiable de protéger votre composant contre cette erreur consiste à effectuer les appels consume() à l’intérieur d’un rappel whenFinished(). Si l’étendue du service est déjà terminée, le rappel est exécuté immédiatement ; sinon, elle sera exécutée ultérieurement une fois l’étendue terminée.
REMARQUE : Il ne s’agit pas d’un rappel asynchrone. L’initialisation de ServiceScope est généralement peu coûteuse et de courte durée. Toutefois, le flux de contrôle passe souvent par de nombreux constructeurs et classes de base, ce qui peut être simplifié à l’aide de whenFinished().