Passer au contenu

Souscriptions

En plus de récupérer des données à l’aide de requêtes et de modifier des données à l’aide de mutations, la spécification GraphQL prend en charge un troisième type d’opération, appelé subscription. Les souscriptions GraphQL permettent d’envoyer des données du serveur aux clients qui choisissent d’écouter les messages en temps réel du serveur. Les souscriptions sont similaires aux requêtes en ce sens qu’elles spécifient un ensemble de champs à livrer au client, mais au lieu de retourner immédiatement une seule réponse, une connexion est ouverte et un résultat est envoyé au client chaque fois qu’un événement particulier se produit sur le serveur.

Un cas d’utilisation courant pour les souscriptions est de notifier le client de certains événements, par exemple la création d’un nouvel objet, des champs mis à jour, etc. (lisez plus ici).

Activer les souscriptions avec le pilote Apollo

Pour activer les souscriptions, définissez la propriété installSubscriptionHandlers sur true.

Configuration du module GraphQL
GraphQLModule.forRoot<ApolloDriverConfig>({
driver: ApolloDriver,
installSubscriptionHandlers: true,
});

Pour switcher vers le package graphql-ws, utilisez la configuration suivante :

Configuration du module GraphQL pour graphql-ws
GraphQLModule.forRoot<ApolloDriverConfig>({
driver: ApolloDriver,
subscriptions: {
'graphql-ws': true,
},
});

Premier code

Pour créer une souscription en utilisant l’approche de premier code, nous utilisons le décorateur @Subscription() (exporté du package @nestjs/graphql) et la classe PubSub du package graphql-subscriptions, qui fournit une simple API de publication/souscription.

Le gestionnaire de souscription suivant s’occupe de se souscrire à un événement en appelant PubSub#asyncIterator. Cette méthode prend un seul argument, le triggerName, qui correspond à un nom de sujet d’événement.

Gestionnaire de souscription
const pubSub = new PubSub();
@Resolver(() => Author)
export class AuthorResolver {
@Subscription(() => Comment)
commentAdded() {
return pubSub.asyncIterator('commentAdded');
}
}

Publier

Pour publier l’événement, nous utilisons la méthode PubSub#publish. Cela est souvent utilisé dans une mutation pour déclencher une mise à jour côté client lorsque une partie de l’objet graphique a changé. Par exemple :

Ajouter un commentaire
@Mutation(() => Post)
async addComment(
@Args('postId', { type: () => Int }) postId: number,
@Args('comment') comment: CommentInput,
) {
const newComment = await this.commentsService.addComment({ id: postId, comment });
await pubSub.publish('commentAdded', { commentAdded: newComment });
return newComment;
}

Comme mentionné, la souscription, par définition, retourne une valeur et cette valeur a une structure. Regardez encore une fois la SDL générée pour notre souscription commentAdded :

type Subscription {
commentAdded: Comment!
}

Cela nous dit que la souscription doit retourner un objet avec une propriété de niveau supérieur nommée commentAdded qui a une valeur qui est un objet Comment. L’important à noter est que la forme de la charge utile de l’événement émise par la méthode PubSub#publish doit correspondre à la forme de la valeur attendue pour être retournée par la souscription. Donc, dans notre exemple ci-dessus, l’instruction pubSub.publish('commentAdded', { commentAdded: newComment }) publie un événement commentAdded avec la charge utile de forme appropriée. Si ces formes ne correspondent pas, votre souscription échouera lors de la phase de validation GraphQL.

Filtrage des souscriptions

Pour filtrer des événements spécifiques, définissez la propriété filter sur une fonction de filtre. Cette fonction agit de manière similaire à la fonction passée à un tableau filter. Elle prend deux arguments : payload contenant la charge utile de l’événement (telle qu’envoyée par l’éditeur d’événements), et variables prenant tous les arguments passés lors de la demande de souscription. Elle retourne un booléen déterminant si cet événement doit être publié aux auditeurs du client.

Souscription avec filtrage
@Subscription(() => Comment, {
filter: (payload, variables) => payload.commentAdded.title === variables.title,
})
commentAdded(@Args('title') title: string) {
return pubSub.asyncIterator('commentAdded');
}

Payload de souscription

Pour modifier le payload de l’événement publié, définissez la propriété resolve sur une fonction. La fonction reçoit le payload de l’événement (tel qu’envoyé par l’éditeur d’événements) et retourne la valeur appropriée :

Souscription avec résolve
@Subscription(() => Comment, {
resolve: value => value,
})
commentAdded() {
return pubSub.asyncIterator('commentAdded');
}

Le même construction fonctionne avec des filtres.

type Subscription {
...
}

Cet exemple montre comment gérer les souscriptions en utilisant un modèle de développement avec NestJS et GraphQL. Il décrit comment les activer, publier des événements, et gérer les paramètres et payloads de manière efficace.