You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Nest.js GraphQL订阅中使用Ix AsyncIterator及相关报错排查

问题根因

NestJS GraphQL的订阅处理器默认要求AsyncIterator产出的是完整的查询响应对象,而非字段的直接值。你当前直接产出数字类型值,处理器会尝试从值中读取与订阅字段同名的counter属性,数字类型不存在该属性,最终取到null值,触发非空字段报错。

解决方案

方案1:调整AsyncIterator的产出结构

每次产出的对象包含和订阅字段同名的属性即可,两种代码实现修改如下:

原生AsyncGenerator版本

async function* generateSequence(start, end) {
  for (let i = start; i <= end; i++) {
    await new Promise((resolve) => setTimeout(resolve, 1000));
    // 嵌套与字段名对应的对象结构
    yield { counter: i };
  }
}

@Resolver((of) => –)
export class TestResolver {
  constructor() {}

  @Subscription((returns) => Number)
  counter(): AsyncIterator<number> {
    return generateSequence(1, 100);
  }
}

Ix实现版本

import { map } from 'ix/operators';

@Resolver((of) => –)
export class TestResolver {
  constructor() {}

  @Subscription((returns) => Number)
  counter(): AsyncIterator<number> {
    return from([1, 2, 3, 4, 5, 6]).pipe(
      map(num => ({ counter: num }))
    )[Symbol.asyncIterator]();
  }
}

方案2:通过resolve参数提取字段值

如果不想修改AsyncIterator的产出逻辑,可以在@Subscription装饰器中新增resolve配置,手动指定字段返回值的提取规则:

async function* generateSequence(start, end) {
  for (let i = start; i <= end; i++) {
    await new Promise((resolve) => setTimeout(resolve, 1000));
    // 保持原有直接产出数字的逻辑
    yield i;
  }
}

@Resolver((of) => –)
export class TestResolver {
  constructor() {}

  @Subscription(() => Number, {
    resolve: (rawValue) => rawValue
  })
  counter(): AsyncIterator<number> {
    return generateSequence(1, 100);
  }
}

额外检查项

如果修改后仍然报错,可以确认两点:

  • 你的GraphQL Schema中Subscription.counter字段是否定义为非空类型,确保AsyncIterator不会产出undefined、null值
  • 确认NestJS配置中已经正确启用订阅传输层(subscriptions-transport-ws或graphql-ws)

内容的提问来源于stack exchange,提问作者DaSch

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 09:45:04