极客时间对于推广渠道会有返利优惠,比如山月在极客时间买了一门课,再把课程分享给好友购买,这时极客时间会向山月返利20元左右。
而我现在做了一个返利平台,你可以在上边通过山月的链接购买课程,此时极客时间会向我返利。为了共同学习,而你可以添加我的微信 (shanyue94),我将把极客时间给我的返利发一个红包全部返给你

graphql 仅仅提供了 schema 与 operation/query 的用法,当我们在 web 中使用 graphql 时,就需要使用 HTTPgraphql 隔离为 clientserver 两端。想象一个流程:

  1. 前端发送 operation 到后端
  2. 后端维护一个 schema
  3. 后端根据前端的 operation 对照自己的 schema,查询出数据返回给前端

# Request

前端需要根据自己构造的 query 去后端请求数据,而一个 query 可以由以下几个元素构成,通过 get/post 传递数据。而目前流行的框架比如 apollo-server (opens new window),也是这样处理

  • query
  • operationName
  • variables

在客户端无需多余的库进行支持,仅仅按照以前的方式组织 Body 发送数据即可。当然为了更好的缓存及类型提示,在前端也可以使用 apollo-client 一些库协助进行 GraphQL 查询。

// url 统一入口,但可以使用 operationName 作为 querystring 方便 debug
const url = '/graphql?HELLO'

// 如果是 POST 请求,构造以下 body 数据
const body = {
  query: 'query HELLO { hello }',
  operationName: 'HELLO',
  variables: {}
}

// 如果是 GET 请求,构造 query string
const qs = querystring.encode(body)

// 向后端发送请求数据
const response = await fetch(url, {
  body
}).then(res => res.json())
// {
//   data: {
//     hello: 'hello, world' 
//   },
//   errors: null
// }

# Response: 一个简单的 GraphQL Server

对于 GraphQL 而言,前端仅仅是构造请求,而无需对 Query 进行解析,最重要的工作量放在服务端实现,如解析 GraphQL、执行 Operation 等。

我们在这里手动实现一个简单的 GraphQL Server。

import http from 'node:http'
import getRawBody from 'raw-body'
import { graphql } from 'graphql'
import { makeExecutableSchema } from '@graphql-tools/schema'

class GraphQLServer {
  constructor ({ typeDefs, resolvers }) {
    this.schema = makeExecutableSchema({
      typeDefs,
      resolvers
    })
  }

  callback () {
    return async (req, res) => {
      const buffer = await getRawBody(req)
      const {
        query,
        operationName,
        variables
      } = JSON.parse(buffer.toString())
      const result = await graphql({
        schema: this.schema,
        source: query,
        variableValues: variables,
        operationName
      })
      res.end(JSON.stringify(result))
    }
  }

  listen (...args) {
    const server = http.createServer(this.callback())
    server.listen(...args)
  }
}

export default GraphQLServer

如此,我们在后端仅仅需要关注如何写好 Schema?

import GraphQLServer from './index.mjs'

const typeDefs = `
  type Book {
    title: String
    author: String
  }

  type Query {
    books: [Book]
  }
`

const books = [
  {
    title: '三国演义',
    author: '施耐庵',
  },
  {
    title: '西游记',
    author: '罗贯中',
  },
]

const resolvers = {
  Query: {
    books: () => {
      return books
    }
  }
}

const app = new GraphQLServer({ typeDefs, resolvers })

app.listen(4000)

关于山月

我的项目:
我的微信:shanyue94,欢迎交流
Last Updated: 2/27/2022, 7:45:54 PM