NodeJS 无法使用graphql-ws订阅获取初始数据

cuxqih21  于 2022-11-04  发布在  Node.js
关注(0)|答案(1)|浏览(248)

我对使用graphql-ws和graphql-yoga服务器还很陌生,所以如果这是一个天真的问题或我的错误,请原谅我。
我看过graphql-ws文档,它把模式写成了参数,不幸的是,文档中使用的模式定义缺少一个引用。

  • 在添加一个新的待办事项(使用addTodo)后,它会显示两个待办事项。* 因此,我相信无论何时在Yoga Graphiql资源管理器上运行订阅,它都无法返回初始待办事项列表。

它应该在模式定义中订阅和发布初始待办事项后立即显示。我的理解是,在模式定义中缺少了一些东西,当尝试访问 Yoga Graphiql explorer 时,没有显示待办事项列表。
有没有人有过类似的经历,并能够解决它?我错过了什么?

使用的库

后端

  • 图形瑜伽
  • 工作站
  • 图形-ws
    前端
  • 实心-js
  • 旺卡
    待办事项-已在架构中声明
  1. {
  2. id: "1",
  3. title: "Learn GraphQL + Solidjs",
  4. completed: false
  5. }

截图

代码段

结构描述定义

  1. import { createPubSub } from 'graphql-yoga';
  2. import { Todo } from "./types";
  3. let todos = [
  4. {
  5. id: "1",
  6. title: "Learn GraphQL + Solidjs",
  7. completed: false
  8. }
  9. ];
  10. // channel
  11. const TODOS_CHANNEL = "TODOS_CHANNEL";
  12. // pubsub
  13. const pubSub = createPubSub();
  14. const publishToChannel = (data: any) => pubSub.publish(TODOS_CHANNEL, data);
  15. // Type def
  16. const typeDefs = [`
  17. type Todo {
  18. id: ID!
  19. title: String!
  20. completed: Boolean!
  21. }
  22. type Query {
  23. getTodos: [Todo]!
  24. }
  25. type Mutation {
  26. addTodo(title: String!): Todo!
  27. }
  28. type Subscription {
  29. todos: [Todo!]
  30. }
  31. `];
  32. // Resolvers
  33. const resolvers = {
  34. Query: {
  35. getTodos: () => todos
  36. },
  37. Mutation: {
  38. addTodo: (_: unknown, { title }: Todo) => {
  39. const newTodo = {
  40. id: "" + (todos.length + 1),
  41. title,
  42. completed: false
  43. };
  44. todos.push(newTodo);
  45. publishToChannel({ todos });
  46. return newTodo;
  47. },
  48. Subscription: {
  49. todos: {
  50. subscribe: () => {
  51. const res = pubSub.subscribe(TODOS_CHANNEL);
  52. publishToChannel({ todos });
  53. return res;
  54. }
  55. },
  56. },
  57. };
  58. export const schema = {
  59. resolvers,
  60. typeDefs
  61. };

服务器后端

  1. import { createServer } from "graphql-yoga";
  2. import { WebSocketServer } from "ws";
  3. import { useServer } from "graphql-ws/lib/use/ws";
  4. import { schema } from "./src/schema";
  5. import { execute, ExecutionArgs, subscribe } from "graphql";
  6. async function main() {
  7. const yogaApp = createServer({
  8. schema,
  9. graphiql: {
  10. subscriptionsProtocol: 'WS', // use WebSockets instead of SSE
  11. },
  12. });
  13. const server = await yogaApp.start();
  14. const wsServer = new WebSocketServer({
  15. server,
  16. path: yogaApp.getAddressInfo().endpoint
  17. });
  18. type EnvelopedExecutionArgs = ExecutionArgs & {
  19. rootValue: {
  20. execute: typeof execute;
  21. subscribe: typeof subscribe;
  22. };
  23. };
  24. useServer(
  25. {
  26. execute: (args: any) => (args as EnvelopedExecutionArgs).rootValue.execute(args),
  27. subscribe: (args: any) => (args as EnvelopedExecutionArgs).rootValue.subscribe(args),
  28. onSubscribe: async (ctx, msg) => {
  29. const { schema, execute, subscribe, contextFactory, parse, validate } =
  30. yogaApp.getEnveloped(ctx);
  31. const args: EnvelopedExecutionArgs = {
  32. schema,
  33. operationName: msg.payload.operationName,
  34. document: parse(msg.payload.query),
  35. variableValues: msg.payload.variables,
  36. contextValue: await contextFactory(),
  37. rootValue: {
  38. execute,
  39. subscribe,
  40. },
  41. };
  42. const errors = validate(args.schema, args.document);
  43. if (errors.length) return errors;
  44. return args;
  45. },
  46. },
  47. wsServer,
  48. );
  49. }
  50. main().catch((e) => {
  51. console.error(e);
  52. process.exit(1);
  53. });
zzwlnbp8

zzwlnbp81#

应用这些更改

  1. Mutation: {
  2. addTodo: (_: unknown, { title }: Todo) => {
  3. const newTodo = {
  4. id: "" + (todos.length + 1),
  5. title,
  6. completed: false
  7. };
  8. todos.push(newTodo);
  9. publishToChannel({ todos });
  10. return newTodo;
  11. },
  12. Subscription: {
  13. todos: {
  14. subscribe: () => {
  15. return Repeater.merge(
  16. [
  17. new Repeater(async (push, stop) => {
  18. push({ todos });
  19. await stop;
  20. }),
  21. pubSub.subscribe(TODOS_CHANNEL),
  22. ]
  23. )
  24. }
  25. },
  26. },

首先,npm i @中继器js/中继器,然后导入中继器

展开查看全部

相关问题