资讯专栏INFORMATION COLUMN

Graphql实践——像axios一样使用Graphql

mumumu / 643人阅读

摘要:初始化项目使用初始化项目安装项目结构如下接口所有接口对封装接下来对进行封装,加上中间件实现类似于拦截器的效果。

Graphql尝鲜

在只学习graphql client端知识的过程中,我们常常需要一个graphql ide来提示graphql语法,以及实现graphql的server端来进行练手。
graphql社区提供了graphiql让我们使用

graphiql (npm):一个交互式的运行于浏览器中的 GraphQL IDE.

但graphiql提供的live demo基本打不开,难道刚接触graphql就要自己实现graphql的server端?
好在github用graphql写了一套api,我们可以去这里,登陆后即可体验一把graphql。


关于graphql的基础知识可以去这里看看

graphql client端选择

graphql在前端实现有以下方案。

Relay (github) (npm):Facebook 的框架,用于构建与 GraphQL 后端交流的 React 应用。  
Apollo Client (github):一个强大的 JavaScript GraphQL 客户端,设计用于与 React、React Native、Angular 2 或者原生 JavaScript 一同工作。
graphql-request:一个简单的弹性的 JavaScript GraphQL 客户端,可以运行于所有的 JavaScript 环境(浏览器,Node.js 和 React Native)—— 基本上是 fetch 的轻度封装。
Lokka:一个简单的 JavaScript GraphQL 客户端,可以运行于所有的 JavaScript 环境 —— 浏览器,Node.js 和 React Native。
nanogql:一个使用模板字符串的小型 GraphQL 客户端库。

从npm download数量上看Apollo Client是最多的,并且Apollo也有服务端的解决方案,所以这里选择Apollo Client作为graphql的client端
apollo client对于web 框架都有具体的实现,但是我更希望能像axios那样去使用graphql,而不是每套web框架都要去学一下具体实现,那样会折腾死自己。

初始化项目
// 使用vue-cli初始化项目
vue init webpack-simple my-project
npm i
安装graphql
npm i apollo-cache-inmemory apollo-client apollo-link apollo-link-http 
npm i graphql graphql-tag
项目结构如下
.
├── index.html
├── package.json
├── package-lock.json
├── README.md
├── src
│   ├── App.vue
│   ├── graphql                            // 接口
│   │   ├── search.graphql
│   │   └── index.js                       // export所有接口
│   ├── main.js
│   └── utils
│       └── graphql.js                    // 对Apollo-client封装
└── webpack.config.js
apollo-client

接下来对apollo-client进行封装,加上中间件(实现类似于axios拦截器的效果)。
graphql.js

import ApolloClient from "apollo-client"
import { InMemoryCache } from "apollo-cache-inmemory"
import { HttpLink } from "apollo-link-http"
import { onError } from "apollo-link-error"
import { ApolloLink, from } from "apollo-link"

const token = "598ffa46592d1c7f57ccf8173e47290c6db0d549"

const Middleware = new ApolloLink((operation, forward) => {
  // request时对请求进行处理
  console.log("Middleware", operation, forward)
})
const Afterware = new ApolloLink((operation, forward) => {
  return forward(operation).map(response => {
    // 服务器返回数据
    console.log("Afterware--response", response)
    return response
  })
})
const errorLink = onError(({ graphQLErrors, networkError }) => {
  if (graphQLErrors)
    graphQLErrors.map(({ message, locations, path }) =>
      console.log(
        `[GraphQL error]: Message: ${message}, Location: ${locations}, Path: ${path}`,
      ),
    );
  if (networkError) console.log(`[Network error]: ${networkError}`);
});

const httpLink = new HttpLink({
  uri: "https://api.github.com/graphql", // 配置请求url 
  headers: {                             // 配置header
    Authorization: `Bearer ${token}`
  }
})
const cache = new InMemoryCache()       // 缓存
export default new ApolloClient({
  link: from([Middleware, Afterware, errorLink, httpLink]),
  cache
})

配置webpack支持.graphql文件

     // 在rules下添加以下规则
      {
        test: /.(graphql|gql)$/,
        exclude: /node_modules/,
        loader: "graphql-tag/loader",
      }

search.graphql

query searchR ($keyword: String!) {
    search (query: $keyword , type: REPOSITORY){
        userCount
    }
}

在/graphql/index.js export所有接口

import client from "../utils/graphql"
// import gql from "graphql-tag"
import * as searchGql from "./search.graphql"
/** searchGql模块 **/
export const search = (params) => client.query({query: searchGql.search, variables: params})

到这里我们已经可以直接调用/graphql/下导出的function

使用github接口实现一个简单的搜索功能


具体实现就不贴出来了,全部代码已经放到github,欢迎star。
run的时候有记得把token换成自己的,因为我的token有可能已经失效。

Graphql分页

graphql实现分页有以下两种方式:

基于偏移量,需要提供第几页, 每页的数量

基于游标或者id,提供每页数量,与 游标/id。

对于游标分页Relay(Facebook家的Graphql库) 定了一套规范 Relay-style cursor pagination

基于偏移量的分页实现简单,但存在以下问题:

性能问题,虽然可以使用 “延迟关联” 解决,但会使sql语句变得复杂

# 假设 有一个 product商品表,当商品表数量足够多时,这个查询会变得非常缓慢,
SELECT id, name FROM product LIMIT 1000, 20;
# 如果我们提供一个边界值,比如id,无论翻页到多么后面,其性能都会很好
SELECT id, name FROM product WHERE id > 1000 LIMIT 20;

删除列表数据时,导致获取下一页的数据缺失

# 假设 总共有11条数据,一页显示10条,总页数为 2 页。
# 当调用接口删除 第 1 页的 1 条数据,然后进行翻页时,因为只剩下10条数据,所以下面的sql会查不到数据。
SELECT id, name FROM product LIMIT 10, 10;

基于游标/ID 的分页,也存在硬伤:

如何实现跳往第 n 页的功能
难道要获取 相应的游标再进行翻页? 所以它更适用于无限加载,或者只有 上一页/下一页 的情景上,对于跳往第n页还是需要用到基于偏移量的分页。

所以我们需要同时支持这两种分页。

Relay 式的游标分页

Relay 定义了 PageInfoEdgesEdge TypesNodeCursor等对象 用于实现灵活的分页。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/95829.html

相关文章

  • Apollo GraphQL 在 webapp 中应用的思考

    摘要:在中应用的思考原文发表在简介熟悉的同学可直接跳过这一章,从实践一章看起。这也是官方建议的最佳实践。也就是说,只有在客户端提交了包含相应字段的时,才会真正去发送相应的请求。在客户端与服务端均不考虑缓存的情况,客户端反而会少一个请求。。。 Apollo GraphQL 在 webapp 中应用的思考 原文发表在: https://github.com/kuitos/kui... 简介 熟悉...

    weapon 评论0 收藏0
  • GraphQL 科普 前端向

    摘要:样例前端传入字段和结构。后台按照前端的需求返回数据。则将前后台通信直接分为两大类和。顾名思义,是默认的操作符,代表查询,是不会给服务端带来副作用的请求。文档文档部分文档就是前端向后台描述所需的字段。降低前后端沟通成本。 简介 showImg(https://segmentfault.com/img/bVbmKX5?w=150&h=150); GraphQL是基于「类型系统」来执行查询的...

    Bmob 评论0 收藏0
  • 2017 年崛起的 JS 项目

    摘要:通过对比各项目过去个月在上新增数量,来评估其在年度的受关注程度,进而选出年度领域崛起的明星项目。也许正因为上述最后一点,在中国拥有大量的拥趸。不仅被中国最大的电商平台阿里巴巴使用,也获得了与这些公司青睐。 共 4741 字,读完需 8 分钟,速读 2 分钟。我有幸参与了该项目的部分中文版翻译、校对工作,感谢 Sacha Grief,Micheal Ramberu 的统计整理,以及 Fr...

    gaara 评论0 收藏0
  • GraphQL学习之实践

    摘要:前言两篇文章学完了基础篇原理篇,接下去便是实践的过程,这个实践我们使用了如下技术栈去实现一套任务管理系统,源码就不公开了等稳定后再发布。后续我所在的公司网关团队会持续实践,争取贡献出更多的解决方案。前言 两篇文章学完了GraphQL(基础篇, 原理篇),接下去便是实践的过程,这个实践我们使用了如下技术栈去实现一套任务管理系统,源码就不公开了, 等稳定后再发布。效果如下: showImg(ht...

    Drinkey 评论0 收藏0
  • GraphQL java工程化实践

    摘要:我在工程实践中直接使用类作为对应实体类的。因此我的结论是,此库并不适用于我的工程实践。工程实践中对其应用方式的考虑在的官方教程中建议针对每请求创建新的实例,查询请求结束则实例们的生命周期结束。 因为自己写过基于react的前端应用,因此一看到GraphQL就被深深吸引,真是直击痛点啊!服务端开发一直是基于java, Spring的,因此开始研究如何在现有工程框架下加入graphql的支...

    MSchumi 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<