Dvl*_*lpr 5 graphql apollo-client angular nestjs
我已经完成了一个 nodejs 后端Nestjs,我正在使用Graphql. 我的前端是 Ionic/Angular,使用 Apollo-angular 来处理 graphql 的东西。
我在订阅数据添加/更改时遇到问题。Playground(由 Nestjs 提供)工作得很好,这让我暗示问题出在前端。
我有game并且scores在我的数据模型中,每个分数都属于一个游戏。在前端,我试图聆听添加到特定游戏的新分数。
这是我的一个片段resolver:
@Mutation(returns => Score)
async addScore(@Args('data') data: ScoreInput): Promise<IScore> {
return await this.scoresService.createScore(data);
}
@Subscription(returns => Score, {
filter: (payload, variables) => payload.scoreAdded.game + '' === variables.gameId + '',
})
scoreAdded(@Args('gameId') gameId: string) {
return this.pubSub.asyncIterator('scoreAdded');
}
Run Code Online (Sandbox Code Playgroud)
这是service方法:
async createScore(data: any): Promise<IScore> {
const score = await this.scoreModel.create(data);
this.pubSub.publish('scoreAdded', { scoreAdded: score });
}
Run Code Online (Sandbox Code Playgroud)
这些在我的 schema.gql 中:
type Score {
id: String
game: String
result: Int
}
type Subscription {
scoreAdded(gameId: String!): Score!
}
Run Code Online (Sandbox Code Playgroud)
根据Apollo-angular的文档,在我的前端,我有这样的服务:
import { Injectable } from '@angular/core';
import { Subscription } from 'apollo-angular';
import { SCORE_ADDED } from './graphql.queries';
@Injectable({
providedIn: 'root',
})
export class ScoreListenerService extends Subscription {
document = SCORE_ADDED;
}
Run Code Online (Sandbox Code Playgroud)
这是在前端的 graphql.queries 中:
export const SCORE_ADDED = gql`
subscription scoreAdded($gameId: String!) {
scoreAdded(gameId: $gameId) {
id
game
result
}
}
`;
Run Code Online (Sandbox Code Playgroud)
我在我的组件中使用这样的服务:
this.scoreListener.subscribe({ gameId: this.gameId }).subscribe(({ data }) => {
const score = data.scoreAdded;
console.log(score);
});
Run Code Online (Sandbox Code Playgroud)
有了这一切,我的前端给了我一个错误 ERROR Error: GraphQL error: Cannot return null for non-nullable field Subscription.scoreAdded.
在 Playground 中进行这样的订阅工作,完全没有问题。
subscription {
scoreAdded(gameId: "5d24ad2c4cf6d3151ad31e3d") {
id
game
result
}
}
Run Code Online (Sandbox Code Playgroud)
我注意到,如果我resolve像这样在后端的解析器中使用:
@Subscription(returns => Score, {
resolve: value => value,
filter: (payload, variables) => payload.scoreAdded.game + '' === variables.gameId + '',
})
scoreAdded(@Args('gameId') gameId: string) {
return this.pubSub.asyncIterator('scoreAdded');
}
Run Code Online (Sandbox Code Playgroud)
前端中的错误消失了,但它搞砸了订阅中的数据,操场在每个属性中获得了带有 null 的附加分数,并且根本不会触发前端中的订阅。
任何帮助,我在这里做错了什么? 在我看来,我的前端不正确,但我不确定这是我的错误还是可能是 Apollo-angular 中的错误...
好的,我的问题解决了。正如我怀疑的那样,问题出在前端代码中。所以我在后端实现 Nestjs 的方式没有任何问题。事实证明这是我的一个愚蠢的错误,没有初始化订阅的 WS,这在此处得到了明确的解释https://www.apollographql.com/docs/angular/features/subscriptions/。
所以,我改变了这个
const graphqlUri = 'http://localhost:3000/graphql';
export function createApollo(httpLink: HttpLink) {
return {
link: httpLink.create({ graphqlUri }),
cache: new InMemoryCache(),
defaultOptions: {
query: {
fetchPolicy: 'network-only',
errorPolicy: 'all',
},
},
};
}
Run Code Online (Sandbox Code Playgroud)
对此
const graphqlUri = 'http://localhost:3000/graphql';
const wsUrl = 'ws://localhost:3000/graphql';
export function createApollo(httpLink: HttpLink) {
const link = split(
// split based on operation type
({ query }) => {
const { kind, operation } = getMainDefinition(query);
return kind === 'OperationDefinition' && operation === 'subscription';
},
new WebSocketLink({
uri: wsUrl,
options: {
reconnect: true,
},
}),
httpLink.create({
uri: graphqlUri,
})
);
return {
link,
cache: new InMemoryCache(),
defaultOptions: {
query: {
fetchPolicy: 'network-only',
errorPolicy: 'all',
},
},
};
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3052 次 |
| 最近记录: |