grahql极简入门教程(基于react+graphql-yoga+urql)⑨

215 阅读3分钟

本文是graphql极简入门教程的第九篇,并且也是最后一篇,内容主要讲述graphql的实时订阅功能。

graphql极简入门教程目录:

👉🏻点击进入本教程github仓库

实时graphql订阅

graphql的实时订阅是基于WebSockets技术实现,前端将会与后端进行一个长连接通讯,具体的描述也请查看阮一峰老师的教程👉🏻WebSocket 教程,笔者在这就不过多赘述了。

在后面的内容中,将会实现用户创建新链接后,发送该事件的实时订阅机制。

定义后端数据结构

与其它类型一样,实时订阅有一个Subscription类。

因此根据需求,在src/server/schema.graphql中有如下的定义,该订阅将会返回一个链接(Link)类型数据:

type Subscription {
    newLink: Link
}

后端具体实现

graphql-yoga中,无需引入额外的包来实现实时订阅,你直接引入createPubSub即可。为了方便后期调用,因此也将订阅(pubSub)也挂载在上下文(context)中:

// ...
const Subscription = require('./resolvers/Subscription');
const { getUserId } = require('./utils');
const {createPubSub} = require("graphql-yoga");

+ const pubSub = createPubSub();

const resolvers = {
    Mutation,
    Query,
    User,
    Link
}

const schema = createSchema({
    typeDefs: fs.readFileSync(path.join(__dirname, 'schema.graphql'), 'utf-8'),
    resolvers: resolvers
})

const prisma = new PrismaClient();

// 基于graphql的scheme,创建一个graphql-yoga的实例
const yoga = createYoga({
    schema,
    context: ({ req }) => {
        return {
            ...req,
            prisma,
+            pubSub,
            userId: req && req.headers.authorization
                ? getUserId(req)
                : null
        }
    }
})

// 基于实例化后的yoga,创建一个server
const server = createServer(yoga)

// 启动server
server.listen(4000, () => {
    console.info('Server is running on http://localhost:4000/graphql')
})

接下来,在src/server/resolvers文件夹中,新建Subscription.js文件,编写订阅逻辑:

function newLinkSubscribe(parent, args, context, info) {
    // ①
    return context.pubSub.subscribe("NEW_LINK")
}

const newLink = {
    subscribe: newLinkSubscribe,
    resolve: payload => {
        // ②
        return payload
    },
}
​
module.exports = {
    newLink,
}

在这里实现了一个订阅的方法,用挂载在上下文中的pubSub,来订阅NEW_LINK事件。

由于对于返回的数据没有任何处理,因此在②中直接返回了payload

接着需要在src/server/resolvers/Mutation.js文件中,添加下面这一行,在创建链接完成后,推送这个信息:

async function post(parent, args, context) {
    const { userId } = context;

    const newLink = await context.prisma.link.create({
        data: {
            url: args.url,
            description: args.description,
            postedBy: { connect: { id: userId } },
        }
    });

+    context.pubSub.publish("NEW_LINK", newLink);

    return newLink;
}

最后,需要再src/server/index.js文件中,添加Subscription引用即可:

//...
+ const Subscription = require('./resolvers/Subscription');
const {createPubSub} = require("graphql-yoga");
​
const pubSub = createPubSub();
​
const resolvers = {
    Mutation,
    Query,
    User,
    Link,
+    Subscription,
}
​
const schema = createSchema({
    typeDefs: fs.readFileSync(path.join(__dirname, 'schema.graphql'), 'utf-8'),
    resolvers: resolvers
})
//...

测试效果

打开http://localhost:4000/graphq页面,并在下面的位置,将自己的token粘贴进去:

接着输入下面的内容,创建链接:

请注意,先粘贴暂时不要执行

mutation {
  post(url: "baidu.com", description: "百度一下") {
    id
  }
}

image-20230212201601496

接下来再打开一个http://localhost:4000/graphq页面,将下面的内容粘贴进入,并且点击执行按钮。此时你将会看到一个一直在转圈的loading,证明正在实时监听数据。

subscription {
  newLink {
    id
    url
    description
    postedBy {
      id
      name
      email
    }
  }
}

image-20230212201416820

接下来,执行第一个打开的页面添加链接,此时已经创建成功

image-20230212201639749

这时你再打开第二个链接,就会发现,同样也返回了这个链接的结果,证明监听成功! image-20230212201724049

到这里就完成了所有的教程,原版教程中还有对链接进行按赞功能,由于本文都已经覆盖了这些操作的类似写法,因此笔者就没有在这个教程中讲述了,有兴趣的同学可以戳这里👉🏻www.howtographql.com/react-apoll… 来查看详细教程。

本教程的代码,你可以在github上下载并运行,如果发现有任何问题欢迎issue 仓库地址:github.com/zyc95/hacke…

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 9 天,点击查看活动详情