PubSub 在客户端页面中不起作用,但在 Graphql 游乐场中起作用 - TypeError: data.getPosts is not iterable

Posted

技术标签:

【中文标题】PubSub 在客户端页面中不起作用,但在 Graphql 游乐场中起作用 - TypeError: data.getPosts is not iterable【英文标题】:PubSub does not work in Client page but works in Graphql playground - TypeError: data.getPosts is not iterable 【发布时间】:2021-02-25 03:55:55 【问题描述】:

我正在尝试使用 MongoDB、Express、React、Node、Graphql 和 Apollo 制作一个社交应用程序,我正在关注来自 freecodecamp 的视频:Link to the video

我正在使用 pubsub 来实现实时功能,就像添加新帖子时,它应该会显示在主页中。

我可能错过了某些文件的代码,这就是为什么 我正在删除一个指向包含整个项目的 github 存储库的链接:Link to the github repo

Home.js

import React,  useContext  from 'react';
import  useQuery  from '@apollo/react-hooks';
import  Grid, Transition  from 'semantic-ui-react';

import  AuthContext  from '../context/auth';
import PostCard from '../components/PostCard';
import PostForm from '../components/PostForm';
import  FETCH_POSTS_QUERY  from '../util/graphql';

function Home() 
  const  user  = useContext(AuthContext);
  const  data, loading, error  = useQuery(FETCH_POSTS_QUERY);
  if(data) 
    const  posts  = data || [];
    return (
      <Grid columns=3>
        <Grid.Row className="page-title">
          <h1>Recent Posts</h1>
        </Grid.Row>
        <Grid.Row>
          user && (
            <Grid.Column>
              <PostForm />
            </Grid.Column>
          )
          loading && <h1>Loading posts..</h1>
          data && (
            <Transition.Group>
              posts &&
                posts.map((post) => (
                  <Grid.Column key=post.id style= marginBottom: 20 >
                    <PostCard post=post />
                  </Grid.Column>
                ))
            </Transition.Group>
          )
        </Grid.Row>
      </Grid>
    );
  
  if(error) 
    return error.message;
  

 
  


export default Home;

我渲染了Home.js中的所有帖子

解析器 => posts.js :

const  AuthenticationError, UserInputError  = require('apollo-server');

const Post = require('../../models/Post');
const checkAuth = require('../../util/check-auth');

module.exports = 
  Query: 
    async getPosts() 
      try 
        const posts = await Post.find().sort( createdAt: -1 );
        return posts;
       catch (err) 
        throw new Error(err);
      
    ,
    async getPost(_,  postId ) 
      try 
        const post = await Post.findById(postId);
        if (post) 
          return post;
         else 
          throw new Error('Post not found');
        
       catch (err) 
        throw new Error(err);
      
    
  ,
  Mutation: 
    async createPost(_,  body , context) 
      const user = checkAuth(context);

      if (body.trim() === '') 
        throw new Error('Post body must not be empty');
      

      const newPost = new Post(
        body,
        user: user.id,
        username: user.username,
        createdAt: new Date().toISOString()
      );

      const post = await newPost.save();

      context.pubsub.publish('NEW_POST', 
        newPost: post,
      ).then(()=>
        console.log("working")
      );

      return post;
    ,
    async deletePost(_,  postId , context) 
      const user = checkAuth(context);

      try 
        const post = await Post.findById(postId);
        if (user.username === post.username) 
          await post.delete();
          return 'Post deleted successfully';
         else 
          throw new AuthenticationError('Action not allowed');
        
       catch (err) 
        throw new Error(err);
      
    ,
    async likePost(_,  postId , context) 
      const  username  = checkAuth(context);

      const post = await Post.findById(postId);
      if (post) 
        if (post.likes.find((like) => like.username === username)) 
          // Post already likes, unlike it
          post.likes = post.likes.filter((like) => like.username !== username);
         else 
          // Not liked, like post
          post.likes.push(
            username,
            createdAt: new Date().toISOString()
          );
        

        await post.save();
        return post;
       else throw new UserInputError('Post not found');
    
  ,
  Subscription: 
    newPost: 
      subscribe: (_, __,  pubsub ) => pubsub.asyncIterator('NEW_POST')
    
  
;

解析器 => index.js :

const postsResolvers = require('./posts');
const usersResolvers = require('./users');
const commentsResolvers = require('./comments');

module.exports = 
  Post: 
    likeCount: (parent) => parent.likes.length,
    commentCount: (parent) => parent.comments.length
  ,
  Query: 
    ...postsResolvers.Query
  ,
  Mutation: 
    ...usersResolvers.Mutation,
    ...postsResolvers.Mutation,
    ...commentsResolvers.Mutation
  ,
  Subscription: 
    ...postsResolvers.Subscription
  
;

tyDefs.js:

const  gql  = require('apollo-server');

module.exports = gql`
  type Post 
    id: ID!
    body: String!
    createdAt: String!
    username: String!
    comments: [Comment]!
    likes: [Like]!
    likeCount: Int!
    commentCount: Int!
  
  type Comment 
    id: ID!
    createdAt: String!
    username: String!
    body: String!
  
  type Like 
    id: ID!
    createdAt: String!
    username: String!
  
  type User 
    id: ID!
    email: String!
    token: String!
    username: String!
    createdAt: String!
  
  input RegisterInput 
    username: String!
    password: String!
    confirmPassword: String!
    email: String!
  
  type Query 
    getPosts: [Post]
    getPost(postId: ID!): Post
  
  type Mutation 
    register(registerInput: RegisterInput): User!
    login(username: String!, password: String!): User!
    createPost(body: String!): Post!
    deletePost(postId: ID!): String!
    createComment(postId: String!, body: String!): Post!
    deleteComment(postId: ID!, commentId: ID!): Post!
    likePost(postId: ID!): Post!
  
  type Subscription 
    newPost(    
    id: ID!,
    body: String!,
    createdAt: String!,
    username: String!,
    likeCount: Int!,
    commentCount: Int!): Post!
  
`;

这是我的服务器(后端)的 index.js 文件:

const  ApolloServer, PubSub  = require('apollo-server');
const mongoose = require('mongoose');

const typeDefs = require('./graphql/typeDefs');
const resolvers = require('./graphql/resolvers');
const  MONGODB  = require('./config.js');

const pubsub = new PubSub();

const PORT = process.env.port || 5000;

const server = new ApolloServer(
  typeDefs,
  resolvers,
  context: ( req ) => ( req, pubsub )
);

mongoose
  .connect(MONGODB,   useUnifiedTopology: true ,  useNewUrlParser: true )
  .then(() => 
    console.log('MongoDB Connected');
    return server.listen( port: PORT );
  )
  .then((res) => 
    console.log(`Server running at $res.url`);
  )
  .catch(err => 
    console.error(err)
  )

我只在 index.js 文件中初始化 pubsub, 这是我得到的错误:

TypeError: data.getPosts is not iterable 0.chunk.js:124321

错误截图:

此错误是一个问题,另一个问题是,每当我单击提交时,都会发生相同的错误,但是当我在Graphql Playground 中运行订阅时,帖子出现在客户端页面中,但当我刷新页面时,帖子出现在那里.

【问题讨论】:

为什么每个人都不想回答我的问题,我已经被这个错误困扰了好几个小时了。我是否应该对我的问题进行任何更改,例如添加一些代码而不是 github 存储库?? 你需要把你尝试过的代码放在图片/视频/githubs上 谢谢我把代码放上去,因为代码太多所以没有放 @Naren 我已经添加了一些文件的代码,如果您想添加更多文件,我会添加它。 根据错误消息,我会说,您的 data.getPosts() 不会像您期望的那样返回数组。你能记录下它的输出并查看实际返回的内容吗? 【参考方案1】:

如果您使用的是 Apollo v3,并且在添加帖子时遇到了一些缓存问题:

 const [createPost,  error ] = useMutation(CREATE_POST_MUTATION, 
        variables: values,
        update(proxy, result) 
          const data = proxy.readQuery(
            query: FETCH_POSTS_QUERY,
          );
          proxy.writeQuery(
            query: FETCH_POSTS_QUERY,
            data: 
              getPosts: [result.data.createPost, ...data.getPosts],
            ,
          );
          values.body = "";
        ,
        onError(err) 
     <== also add this so the page doesn't break
          return err;
        ,
      );

【讨论】:

以上是关于PubSub 在客户端页面中不起作用,但在 Graphql 游乐场中起作用 - TypeError: data.getPosts is not iterable的主要内容,如果未能解决你的问题,请参考以下文章

gradle 连续构建技巧在 docker 容器中不起作用

一个函数在我用 Postman 测试时有效,但在我的客户中不起作用

Vimeo - 嵌入在 IE 中不起作用

p12 在 NodeDefaultKeyStore 中工作,但在 WebSphere 的 CellDefaultKeyStore 中不起作用

模态在我的网络服务器中不起作用,但在 localhost 中起作用。这是为啥?

jQuery .on() 方法在 Chrome 中不起作用(但在 IE 和 FF 中起作用)