不久前,我正在开发一个移动应用程序,其功能包括便捷的在线聊天。 现在,我决定写一篇文章,其中简要说明了如何在后端使用apollo服务器和node.js创建聊天,以及如何在客户端响应本机和apollo客户端。
文章分为两部分,以方便阅读。 第一部分包含用于创建应用程序后端的指南,第二部分包含用于创建应用程序前端的指南。
如果您懒于阅读,则可以在
此处和
此处立即在Github'e中查看代码。
作为实现的主要技术,我选择了node.js
koa框架,
postgresql数据库以及GraphQL服务器-apollo
-server-koa 。
首先,生成了一个空的koa2项目,为此,我通过在终端中执行以下命令使用了一个简单的
koa-generator :
$ koa <project name>
然后安装了必要的依赖关系,我使用yarn来完成,但是您可以使用npm。
$ yarn add apollo-server-koa knex objection pg
已安装所有必需的库,现在您可以编写代码
要连接到数据库,您需要描述两个文件,第一个是db.js,它将导出knex客户端实例并允许我们的模型处理来自数据库的数据,第二个是knexfile.js,其中包含用于创建和创建数据库的数据库连接设置。滚动迁移。
db.js代码如下所述,请注意,所有设置均取自环境变量: const db = require('knex')({ client: 'pg', connection: { host : process.env.POSTGRES_HOST, port: process.env.POSTGRES_PORT, user : process.env.POSTGRES_USER, password : process.env.POSTGRES_PASSWORD, database : process.env.POSTGRES_DATABASE } }); module.exports = db;
代码knexfile.js
在此处可用。
现在,您可以描述迁移以创建我们需要的两个表。
这些表本身将尽可能地简单,并且仅包含所需的最小字段集。 创建它们的命令如下:
$ knex migrate:make migration_name
您可以在
此处查看迁移文件。
现在创建实体模型Message和User
class Message extends Model { static get tableName() { return 'messages'; } $beforeInsert() { this.created_at = new Date().toISOString(); } static get relationMappings() { return { user: { relation: Model.BelongsToOneRelation, modelClass: User, join: { from: 'messages.user_id', to: 'users.id' } } }; } }
最有趣的事情仍然存在-连接和配置apollo-server-koa,graphql方案和解析器的描述。
要连接apollo-server-koa,只需添加以下代码行
app.js: const { ApolloServer } = require('apollo-server-koa'); const graphqlSchema = require('./graphqlSchema'); … const apolloServer = new ApolloServer(graphqlSchema); apolloServer.applyMiddleware({ app });
网址: var { app, apolloServer } = require('../app'); ... apolloServer.installSubscriptionHandlers(server);
除了连接apollo-server-koa外,我们还提供了与订阅一起使用的功能,以通知客户聊天中已收到新消息。
已连接Apollo-server-koa,下一步是对带有聊天所需类型的graphql图的描述
input UserInput { username: String! } input MessageInput { text: String! user_id: ID! } type User { id: ID username: String } type Message { id: ID text: String created_at: String user: User } type Query { getLast100Messages: [Message] } type Mutation { findOrCreateUser(user: UserInput!): User createMessage(message: MessageInput!): Message } type Subscription { messageCreated: Message }
电路已准备好,我们描述旋转变压器
用于发送新消息的解析器的示例: const Message = require('../../models/message'); const { pubsub, MESSAGE_CREATED } = require('../../utils'); module.exports = { createMessage: async (obj, { message }, context, info) => { const createdMessage = await Message .query() .insert(message); const resultMessage = await Message .query() .eager('user') .findById(createdMessage.id); pubsub.publish(MESSAGE_CREATED, { messageCreated: resultMessage }); return resultMessage; }, };
有趣的一点是,除了将消息保存在数据库中之外,这里还调用了publish()函数,该消息通知所有订阅者有关MESSAGE_CREATED事件,向他们发送新消息的对象(细心的阅读者会注意到发送者还将收到他的新消息的通知,我们将对此进行进一步处理。对于客户而言,在一个真实的项目中,有必要在后端进行处理,以免在不同客户之间重复逻辑。
其余解析器的代码可以在
此处找到。
聊天的服务器端已准备就绪,如何验证一切正常?
在浏览器中打开
主机 ,您将在其中看到graphql游乐场。
在下一部分中,我们将创建一个移动应用程序。