为什么在Redis上运行GraphQL订阅时会抛出一个错误cannot read property of undefined(阅读'length')?

kmb7vmvb  于 2022-10-31  发布在  Redis
关注(0)|答案(1)|浏览(523)

概述

  • 使用Windows操作系统的笔记本电脑使用GraphQL处理NestJS项目
  • 使用graphql-redis-subscription@2.5.0包试验GraphQL订阅
  • Redis是在一个docker容器中使用的,参见下面的docker-compose.yml
  • 在GraphQL Playground中执行订阅postAdded时出现了问题。在我执行createPost变异之前,它没有挂起以监听事件,而是崩溃了。

我的代码(我只包括一些重要的细节)
posts.resolver.ts

import { Inject, UseGuards } from '@nestjs/common';
import { Args, Context, Mutation, Resolver, Subscription } from '@nestjs/graphql';
import { RedisPubSub } from 'graphql-redis-subscriptions';
import { GraphqlJwtAuthGuard } from '../auth/guards';
import { RequestWithUser } from '../auth/interfaces';
import { PUB_SUB } from '../pubsub/pubsub.module'

const POST_ADDED_EVENT = 'postAdded';

@Resolver(() => Post)
export class PostsResolver {
  constructor(
    private postsService: PostsService,
    @Inject(PUB_SUB) private pubSub: RedisPubSub,
  ) {}

  // my subscription (issue)
  @Subscription(() => Post)
  postAdded() {
    return this.pubSub.asyncIterator(POST_ADDED_EVENT);
  }

  // createPost method
  @Mutation(() => Post)
  @UseGuards(GraphqlJwtAuthGuard)
  async createPost(
    @Args('input') createPostInput: CreatePostInput,
    @Context() context: { req: RequestWithUser },
  ) {
    // just create a new post (assuming it works)
    const newPost = await this.postsService.create(
      createPostInput,
      context.req.user,
    );
    this.pubSub.publish(POST_ADDED_EVENT, { postAdded: newPost });
    return newPost;
  }
}

pubsub.module.ts

import { ConfigService } from '@nestjs/config';
import { RedisPubSub } from 'graphql-redis-subscriptions';
import { Global, Module } from '@nestjs/common';

export const PUB_SUB = 'PUB_SUB';

@Global()
@Module({
  providers: [
    {
      provide: PUB_SUB,
      useFactory: (configService: ConfigService) =>
        new RedisPubSub({
          connection: {
            host: configService.get('REDIS_HOST'),
            port: configService.get('REDIS_PORT'),
          },
        }),
      inject: [ConfigService],
    },
  ],
  exports: [PUB_SUB],
})
export class PubSubModule {}

app.module.ts
第一个
所有环境变量都已在.env文件中定义。

REDIS_HOST="localhost"
REDIS_PORT=6379

在GraphQL Playground中运行yarn start:dev并执行订阅时

subscription {
  postAdded {
    id
    title
    paragraphs
  }
}

它会引发如下错误:

{
  "errors": [
    {
      "message": "Cannot read properties of undefined (reading 'length')",
      "locations": [
        {
          "line": 2,
          "column": 3
        }
      ],
      "path": [
        "postAdded"
      ]
    }
  ]
}

监视NestJS的终端也会引发如下错误:

[Nest] 8080  - 07/21/2022, 9:30:24 AM   ERROR [ExceptionsHandler] Cannot read properties of undefined (reading 'length')
TypeError: Cannot read properties of undefined (reading 'length')
    at JavascriptRedisParser.execute (C:\Users\HP\nestjs-project\node_modules\redis-parser\lib\parser.js:530:38)
    at Object.data (C:\Users\HP\nestjs-project\node_modules\ioredis\built\DataHandler.js:25:20)  
    at TransformOperationExecutor.transform (C:\Users\HP\nestjs-project\node_modules\src\TransformOperationExecutor.ts:207:39)
    at TransformOperationExecutor.transform (C:\Users\HP\nestjs-project\node_modules\src\TransformOperationExecutor.ts:327:31)
    at TransformOperationExecutor.transform (C:\Users\HP\nestjs-project\node_modules\src\TransformOperationExecutor.ts:327:31)
    at TransformOperationExecutor.transform (C:\Users\HP\nestjs-project\node_modules\src\TransformOperationExecutor.ts:327:31)
    at TransformOperationExecutor.transform (C:\Users\HP\nestjs-project\node_modules\src\TransformOperationExecutor.ts:327:31)
    at TransformOperationExecutor.transform (C:\Users\HP\nestjs-project\node_modules\src\TransformOperationExecutor.ts:327:31)
    at ClassTransformer.instanceToPlain (C:\Users\HP\nestjs-project\node_modules\src\ClassTransformer.ts:25:21)
    at Object.classToPlain (C:\Users\HP\nestjs-project\node_modules\src\index.ts:23:27)

我已经安装了所有必要的依赖项,如ioredisgraphql-redis-subscriptions,甚至graphql-subscriptions,但错误仍然存在。Redis似乎也运行正常。
我试过阅读错误日志,但它没有发生在我的源代码中,并对StackOverflow做了一些研究,但似乎都没有解决问题。

hgqdbh6s

hgqdbh6s1#

您是否碰巧使用了全局ClassSerializerInterceptor??因为我今天遇到了同样的问题,我通过删除拦截器解决了这个问题。之所以会发生这种情况,是因为订阅需要接收AsyncIterable的示例,但类序列化程序将其转换为普通对象。
除此之外,我建议您更改GraphQl配置,删除installSubscriptionHandlers,然后按如下方式更改配置:

GraphQLModule.forRoot<ApolloDriverConfig>({
  driver: ApolloDriver,
  playground: true,
  autoSchemaFile: path.join(process.cwd(), 'src/schema.gql'),
  // remove this option: 
  // installSubscriptionHandlers: true,
  // add the following:
  subscriptions: {
    "graphql-ws": true // or config object
  }
}),

您可以在nestjs docs中阅读更多有关它的信息。
我希望这能解决你的问题。

相关问题