我事先知道我的要求很复杂。我希望在我的应用程序中创建一个“实时聊天”系统。
我在Prisma和Apollo Client前端中使用Next.JS / graphql-yoga(服务器快递)。
我的应用程序已经很大,所以我不能太多共享它的代码,但我想知道如何使用GraphQL订阅系统。 (除了我现有的体系结构。)
我看到很多人都在使用“ subscriptions-transport-ws”和专用服务器来进行此操作。而且我找不到任何具体示例。
我的订阅解析器:
const SOMETHING_CHANGED = "something changed";
const Subscription = {
messageSent: {
subscribe(parent, args, ctx, info) {
console.log("GET", ctx.pubsub);
return ctx.pubsub.asyncIterator("post");
}
}
};
module.exports = Subscription;
我的CreateServer文件:
const { GraphQLServer, PubSub } = require("graphql-yoga");
const Mutation = require("./resolvers/Mutation");
const Query = require("./resolvers/Query");
const Subscription = require("./resolvers/Subscription");
const db = require("./db");
const pubsub = new PubSub();
function createServer() {
return new GraphQLServer({
typeDefs: "src/schema.graphql",
resolvers: {
Mutation,
Query,
Subscription
},
resolverValidationOptions: {
requireResolversForResolveType: false
},
context: req => ({ ...req, db, pubsub })
});
}
module.exports = createServer;
我的Index.js后端文件:
require("dotenv").config({ path: "variables.env" });
const createServer = require("./createServer");
const server = createServer();
server.start(
{
cors: {
credentials: true,
origin: process.env.FRONTEND_URL,
},
},
deets => {
console.log(`Server : http://localhost:${deets.port}`);
}
);
我的变异:
async sendMessage(parent, { from, message }, ctx, info) {
const chat = await ctx.db.mutation.createChat({
data: {
from,
message
}
});
ctx.pubsub.publish("post", {
messageSent: {
mutation: "CREATED",
data: chat
}
});
return chat;
}
我的查询与生成的查询相同:
chats: forwardTo("db")
我的前端页面以创建/显示消息:
import React, { Component } from "react";
import { Query, Mutation } from "react-apollo";
import gql from "graphql-tag";
import StyledForm from "../styles/StyledForm";
import Error from "../Error";
const GET_MESSAGE_QUERY = gql`
query GET_MESSAGE_QUERY {
chats {
id
from
message
}
}
`;
const subscription = gql`
subscription Message {
messageSent {
mutation
data {
id
from
message
}
}
}
`;
const SEND_MESSSAGE_MUTATION = gql`
mutation SEND_MESSSAGE_MUTATION($from: String!, $message: String!) {
sendMessage(from: $from, message: $message) {
id
from
message
}
}
`;
class MessageListView extends Component {
componentDidMount() {
this.props.subscribeToMore();
}
render() {
const { data } = this.props;
console.log("DATA 2 ", data);
return (
<ul>
{data.chats.map(msg => (
<li key={msg.id}> {msg.message} </li>
))}
</ul>
);
}
}
class JoinArticle extends Component {
// State
state = {
message: "",
from: "Me"
};
// Handle Change
handleChange = e => {
const { name, value } = e.target;
this.setState({ [name]: value });
};
// Render
render() {
return (
<Query query={GET_MESSAGE_QUERY}>
{({ data, loading, error, subscribeToMore }) => {
if (loading) return <p> Chargement ...</p>;
if (error) return <Error error={error} />;
const more = () =>
subscribeToMore({
document: subscription,
updateQuery: (prev, { subscriptionData }) => {
if (!subscriptionData.data) return prev;
const { mutation, data } = subscriptionData.data.messageSent;
if (mutation !== "CREATED") return prev;
return Object.assign({}, prev, {
GET_MESSAGE_QUERY: [data, ...prev.GET_MESSAGE_QUERY].slice(
0,
20
)
});
}
});
return (
<>
<MessageListView data={data} subscribeToMore={more} />;
<Mutation
mutation={SEND_MESSSAGE_MUTATION}
variables={this.state}
>
{sendMessage => (
<StyledForm>
<fieldset>
<input
type="text"
value={this.state.message}
onChange={this.handleChange}
id="message"
name="message"
placeholder="message"
onKeyDown={async e => {
if (e.key === "Enter") {
e.preventDefault();
await sendMessage();
}
}}
required
/>
</fieldset>
</StyledForm>
)}
</Mutation>
</>
);
}}
</Query>
);
}
}
export default JoinArticle;
如果需要更多信息,请告诉我。如果有人可以帮助我了解订阅以及如何在现有项目中实现聊天系统,则非常感谢。 <3