Graphql 嵌套在类型中的Apollo服务器订阅

Graphql 嵌套在类型中的Apollo服务器订阅,graphql,apollo,apollo-server,Graphql,Apollo,Apollo Server,我正在尝试获取Apollo Server 2中订阅的解析程序。当订阅是顶级字段时(即直接位于schema根目录下的subscription下),它就可以工作 但是,如果订阅包含在另一个类型中,我总是会得到错误订阅字段必须返回Async Iterable。接收:在客户端的websocket连接上未定义——服务器的解析程序永远不会执行 i、 e.该模式适用于: type Subscription { postAdded: Post } 但这一条没有: type Subscription {

我正在尝试获取Apollo Server 2中订阅的解析程序。当订阅是顶级字段时(即直接位于
schema
根目录下的
subscription
下),它就可以工作

但是,如果订阅包含在另一个
类型
中,我总是会得到错误
订阅字段必须返回Async Iterable。接收:在客户端的websocket连接上未定义
——服务器的解析程序永远不会执行

i、 e.该模式适用于:

type Subscription {
  postAdded: Post
}
但这一条没有:

type Subscription {
  post: PostSubscription
}

type PostSubscription {
  postAdded: Post
}
第二种情况下的解析器如下所示,但我尝试了一系列不同的变体,但都没有成功:

Subscription: {
  post: () => ({
    PostSubscription: {}
  })
},
PostSubscription: {
  postAdded: {
    subscribe: () => pubSub.asyncIterator(['postAdded'])
  }
}

错误消息表示您的后期解析程序


    Subscription: {
      post: () => ({
        PostSubscription: {} // This needs to return AsyncIterator
      })
    },

如果我理解正确的话,你想订阅一个postAdded,postdelected,postapdated,这三个都在post下。我知道您希望尝试在同一个模型下命名它们,这有助于更好地组织。但它有一些问题,我稍后会解释

一句忠告: 最好将这3个字段直接放在根订阅字段下。

不是说你做不到,但如果你真的想, 假设您正在订阅


    Subscription{
      post{
         postAdded: Post
         postDeleted: Post
         postUpdated(id:Int!): Post
      }
    }

然后,三个嵌套字段都“共享”同一通道

然后你需要做几件事

  • post的订阅函数返回异步迭代器,不是postAdd,而是post字段
  • 然后在变异函数中,即变异后(添加、更新、删除),您需要确定要发送给客户端的内容 像这样的

    
        Mutation{
           createPost: (_,args,context,info)=>{
              const createdObject = // do create
              pubsub.publish("postChannel", {
                 post:{
                    // do not do postUpdate, postDelete, because there's nothing updated, deleted
                    postAdded:createdObject
                 }
              })
           }
        }
    
    
    response = {
        subscription:{
            postAdded:null
        }
    }
    
    这会让你想做的事情起作用,但这有几个问题。 1.无论何时发生任何更新/创建/删除,都会通知客户机。这可能会给客户提供不正确的信息。像这样 如果客户机订阅了

    subscription{
        post{
            postAdded
        }
    }
    
    然后,当其他人更新帖子时,客户机将得到如下响应

    
        Mutation{
           createPost: (_,args,context,info)=>{
              const createdObject = // do create
              pubsub.publish("postChannel", {
                 post:{
                    // do not do postUpdate, postDelete, because there's nothing updated, deleted
                    postAdded:createdObject
                 }
              })
           }
        }
    
    
    response = {
        subscription:{
            postAdded:null
        }
    }
    
    对于postAdd忽略null可能是可以的。但这对postUpdate来说肯定是个问题。想象一个用户订阅

    subscribe{
        post{
            postUpdate(id:1)
        }
    }
    
    然后有人添加了post,客户端将始终收到通知,因为这三个事件共享同一个通道。 然后他会收到

    response = {
        subscription:{
            postUpdated:null
        }
    }
    
    然后,如果您使用的是apollo客户端,它将从缓存中删除post:1,因为它会认为post为null

    由于这些问题,强烈建议创建多个通道,最好每个模型创建三个通道。并创建三个根级别订阅,而不是嵌套它们


    对于最低有效订阅,我会将您重定向到我为演示订阅而制作的git回购

    感谢您发布此问题,我们正经历完全相同的行为,我帮了我们一个忙,并将您的问题克隆到此处: