Apollo 发布和订阅错误:无法查询字段?

Posted

技术标签:

【中文标题】Apollo 发布和订阅错误:无法查询字段?【英文标题】:Apollo Publish & Subscribe Error: Cannot Query Field? 【发布时间】:2017-02-11 23:13:33 【问题描述】:

我正在学习新的 Apollo pubsub 代码,使用来自 GitHunt-API 和 GitHunt-React 的示例。当我在客户端调用 subscribe 时,我收到控制台日志错误:

“无法在类型“订阅”上查询字段“createIM”。

我试图非常严格地遵循示例代码,但我遗漏了一些东西。

我该如何纠正这个错误?

CREATE_IM.JSX

class CreateIM extends React.Component 
[.....]
    subscribe(fromID, toID, updateCommentsQuery) 
        const SUBSCRIPTION_QUERY = gql`
          subscription IMAdded($fromID: String!, $toID: String!, $msgText: String!)
              createIM(fromID: $fromID, toID: $toID, msgText: $msgText)
                fromID
                toID
                msgText
  

    `;
        this.subscriptionObserver = this.props.client.subscribe(
            query: SUBSCRIPTION_QUERY,
            variables:  fromID: this.fromID, toID: this.toID ,
        ).subscribe(
            next(data) 
                debugger;
                const newComment = data.commentAdded;
                updateCommentsQuery((previousResult) => 
                    // if it's our own mutation, we might get the subscription result
                    // after the mutation result.
                    if (isDuplicateComment(newComment, previousResult.entry.comments)) 
                        return previousResult;
                    
                    // update returns a new "immutable" list with the new comment
                    // added to the front.
                    return update(
                        previousResult,
                        
                            entry: 
                                comments: 
                                    $unshift: [newComment],
                                ,
                            ,
                        
                    );
                );
            ,
            error(err)  debugger; console.error('err', err); , //<== ERROR ON THIS LINE
        );
    

架构

import Resolvers from '/imports/api/resolvers';
import Connectors from '/imports/api/db-connectors';
import  makeExecutableSchema  from 'graphql-tools';

const typeDefinitions = [`

type instant_message 
  id: Int
  fromID: String
  toID: String
  msgText: String

type Query 
  instant_message(fromID: String, toID: String, msgText: String): [instant_message]

type Mutation 
  createIM(
    fromID: String!
    toID: String!
    msgText: String!
  ): instant_message

type Subscription 
  # Subscription fires on every comment added
  IMAdded(fromID: String!, toID: String!, msgText: String!): instant_message


schema 
  query: Query,
  mutation: Mutation
  subscription: Subscription


`];


const executableSchema = makeExecutableSchema(
    typeDefs: typeDefinitions,
    resolvers: Resolvers,
    connectors: Connectors,
    logger: console,
);

export default executableSchema;

订阅(服务器代码)

import  print  from 'graphql-tag/printer';
import  PubSub, SubscriptionManager  from 'graphql-subscriptions';
import schema from '/imports/api/schema';

const pubsub = new PubSub();
const subscriptionManager = new SubscriptionManager(
    schema,
    pubsub,
    setupFunctions: 
        IMAdded: (options, args) => (
            IMAdded: comment => true, //not quite sure yet what validation needs to be here
        ),
    ,
);

export  subscriptionManager, pubsub ;

解决者

const resolvers = 
    Query: 
        instant_message(_, args) 
            var ret = connectors.IM.findAll( where: args ).then((res) => res.map((item) => item.dataValues));
            return ret;
        
    ,
    Mutation: 
        createIM(root, args, context) 
            return Promise.resolve()
                .then(() => (
                    connectors.IM.create(args)
                ))
                .then(([args]) =>
                    connectors.IM.findAll( where: args ).then((res) => res.map((item) => item.dataValues))
                )
                .then(comment => 
                    // publish subscription notification
                    pubsub.publish('IMAdded', comment);
                    return comment;
                );
        ,
  ,
    Subscription: 
        IMAdded(fromID, toID, msgText) 
            // the subscription payload is the comment.
            return msgText;
        ,
    

;

【问题讨论】:

【参考方案1】:

您正在订阅中选择一个突变字段。您必须改用订阅字段。只需更改查询中具有突变的行以使用订阅:

createIM(fromID: $fromID, toID: $toID, msgText: $msgText)

改成这样:

IMAdded(fromID: $fromID, toID: $toID)

如果你的订阅设置正确,那么IMAdded解析器会通过pubsub系统得到变异结果,你可以直接在订阅上选择instant_message的子字段。

另外,请注意我删除了 IMAdded 的 msgText 参数。这真的没有意义。订阅参数可用于过滤消息,但实际消息将通过根值进入。

【讨论】:

我想确保我按照您所说的正确。应该是 ``` subscribe(fromID, toID, updateCommentsQuery) const SUBSCRIPTION_QUERY = gql` 订阅 IMAdded($fromID: String!, $toID: String!, $msgText: String!) `;``` 我可以想到一些其他的变体,这可能是您所建议的。我想确保我得到正确的消息,因为我收到了包含我能想到的所有变体的错误消息,并且我想确保我把这部分做对了,以便正确地继续。 :) 我没有仔细阅读您的代码。我已经更新了我的答案,以解决我认为的实际问题。

以上是关于Apollo 发布和订阅错误:无法查询字段?的主要内容,如果未能解决你的问题,请参考以下文章

React Apollo 显示“react-apollo 仅支持每个 HOC 的查询、订阅或突变”错误

订阅未定义的错误处理 - Apollo 和 Angular 2

React-Apollo 错误:“...仅支持每个 HOC 的查询、订阅或突变”

Apollo 订阅解析器永远不会激活?

需要通过模式拼接来查找连接订阅的错误

如何在 React 中为上传和订阅设置 Apollo 客户端?