除了 Query 和 Mutation ,GraphQL 還提供第三種類型 Subscription。
Subscription 是一種將資料由 server 推向 clinet 的一種方式,而不是 clinet 發送請求後 server 回傳資料。
將 installSubscriptionHandlers 設定為 true
GraphQLModule.forRoot({
installSubscriptionHandlers: true,
})
NestJs Graphql 提供了 @Subscription decorator ,我們會將要使用此類型的函式加上 decorator
接著使用 graphql-subscriptions package 的 PubSub ,提供簡單的 publish(發布) 以及 subscribe(訂閱) 事件 API
調用 PubSub#asyncIterator 來訂閱事件。
事件名稱:commentAdded
我們有兩種方式可以定義事件方法:
//Path: src/authors/authors.resolver.ts
import { Resolver, Query, ID, Args, Subscription, Mutation } from "@nestjs/graphql";
import { PubSub } from 'graphql-subscriptions';
import { AuthorsService } from './authors.service';
import { Author } from './models/author.model';
import { Comment } from './models/comment.model';
const pubSub = new PubSub();
@Resolver(of => Author)
export class AuthorsResolver {
...
// 方法一
// @Subscription(returns => Comment)
// commentAdded() {
// return pubSub.asyncIterator('commentAdded');
// }
// 方法二
@Subscription(returns => Comment, {
name: 'commentAdded',
})
addCommentHandler() {
return pubSub.asyncIterator('commentAdded');
}
}
// Path: src/authors/models/comment.model.ts
@ObjectType()
export class Comment {
@Field({ nullable: true })
comment?: string;
}
調用 PubSub#publish
來發佈事件
type Subscription {
commentAdded: Comment!
}
import { Resolver, Query, ID, Args, Subscription, Mutation } from "@nestjs/graphql";
import { PubSub } from 'graphql-subscriptions';
import { AuthorsService } from './authors.service';
import { Author } from './models/author.model';
import { Comment } from './models/comment.model';
const pubSub = new PubSub();
@Resolver(of => Author)
export class AuthorsResolver {
...
@Mutation(returns => Comment)
addComment(@Args('comment', { type: () => String}) comment: string) {
pubSub.publish('commentAdded', { commentAdded: { comment } });
return { comment };
}
...
}
啟動服務,打開 Playground 進行測試
addComment API 發布事件
subscription 監聽事件
mutation {
addComment(comment: "comment") {
comment
}
}
subscription {
commentAdded {
comment
}
}
先讓 Subscription 進行監聽
在未收到事件之前,它會一直轉圈圈,這很正常
執行 Mutation addComment
回到 Subscription commentAdded,能看到我們成功接收到事件的回傳值
可以多發幾次事件請求,就能看到事件會一直往下增長
對,他是往下,而且不能 scroll !!
想要過濾掉特定事件,可以使用 filter 屬性,它有兩個參數 payload, variables,最後回傳一個 boolean 值,決定是否會將事件發佈給前端監聽器。
payload 是由事件發送者傳過來的參數
variables 是訂閱者所接收到的參數
@Subscription(returns => Comment, {
name: 'commentAdded',
// 加入 filter 以及判斷式
filter: (payload, variables) => {
return payload.commentAdded.title === variables.title
}
})
// 加入訂閱者參數
addCommentHandler(@Args('title') title: string) {
return pubSub.asyncIterator('commentAdded');
}
接著到 playground 進行測試,發布者及訂閱者都多了 title 參數,在上面的判斷是中,我們設定兩者的 title 要一樣訂閱者才能成功接收到事件
讀者可以直接測試,當設定一樣的值,就能收到事件,反之,不一樣的值,subscription 就不會有任何反應
這樣我們就成功利用過濾器,過濾我們想要的事件
subscription | mutation |
---|---|
官方還有 Sehema first 範例說明,由於只是 Schema 產生方式不太一樣,所以我這邊就不在多做說明
以上就是 Subscription 介紹!