Apollo服务器订阅无法识别异步可迭代

问题描述 投票:1回答:1

我对Apollo GraphQL的订阅有问题。尝试启动订阅时,我得到以下回报:

"Subscription field must return Async Iterable. Received: { pubsub: { ee: [EventEmitter], subscriptions: {}, subIdCounter: 0 }, pullQueue: [], pushQueue: [], running: true, allSubscribed: null, eventsArray: [\"H-f_mUvS\"], return: [function return] }"

我还有其他订阅设置,并且功能齐全-因此我可以确认网络服务器设置正确。

我很好奇,是否有人曾经遇到过这个问题。

PR diff中的源代码(这是一个开源项目):https://github.com/astronomer/houston-api/pull/165/files

error in playground

graphql apollo publish-subscribe
1个回答
0
投票

我认为这不是您发布的PR特有的问题。如果任何订阅按原样工作,我会感到惊讶。

您的subscribe函数应返回AsyncIterable,作为错误状态。由于它返回对createPoller的调用,因此createPoller应该返回AsyncIterable。但是,该函数的外观如下:

export default function createPoller(
  func,
  pubsub,
  interval = 5000, // Poll every 5 seconds
  timeout = 3600000 // Kill after 1 hour
) {
  // Gernate a random internal topic.
  const topic = shortid.generate();

  // Create an async iterator. This is what a subscription resolver expects to be returned.
  const iterator = pubsub.asyncIterator(topic);

  // Wrap the publish function on the pubsub object, pre-populating the topic.
  const publish = bind(curry(pubsub.publish, 2)(topic), pubsub);

  // Call the function once to get initial dataset.
  func(publish);

  // Then set up a timer to call the passed function. This is the poller.
  const poll = setInterval(partial(func, publish), interval);

  // If we are passed a timeout, kill subscription after that interval has passed.
  const kill = setTimeout(iterator.return, timeout);

  // Create a typical async iterator, but overwrite the return function
  // and cancel the timer. The return function gets called by the apollo server
  // when a subscription is cancelled.
  return {
    ...iterator,
    return: () => {
      log.info(`Disconnecting subscription ${topic}`);
      clearInterval(poll);
      clearTimeout(kill);
      return iterator.return();
    }
  };
}

所以createPoller创建了一个AsyncIterable,但随后创建了它的浅表副本并返回了它。 graphql-subscriptionsiterallisAsyncIterable用于产生您所看到的错误的检查。由于isAsyncIterable works的方式,浅拷贝不会飞行。您可以自己查看:

const { PubSub } = require('graphql-subscriptions')
const { isAsyncIterable } = require('iterall')

const pubSub = new PubSub()
const iterable = pubSub.asyncIterator('test')
const copy = { ...iterable }
console.log(isAsyncIterable(iterable)) // true
console.log(isAsyncIterable(copy)) // false

因此,createPoller不应直接返回浅表副本,而应直接更改return方法:

export default function createPoller(...) {
  ...
  iterator.return = () => { ... }

  return iterator
}
© www.soinside.com 2019 - 2024. All rights reserved.