初識GraphQL

目錄

  • 什麼是GraphQL
  • 解決了什麼問題
  • GraphQL一個簡單的入門示例

什麼是GraphQL

官方文檔定義:一種用於API的查詢語言, Graph + Query 有如下特色javascript

  1. 請求你所要的數據很少很多
  2. 獲取多個資源只用一個請求
  3. 描述全部可能的類型系統

解決了什麼問題

1. 來講一個實際的場景:

先後端聯調接口一直以來都是特別費勁的一個環節,使用REST接口,接口返回的數據格式,數據類型(有哪些字段,字段的類型)都是後端本身預先定義好的,若是返回的數據格式並非調用者所指望的,做爲前端的咱們能夠經過如下兩種方式去解決html

  • 和後端溝通,該接口(更改數據源)
  • 本身作一些適配工做(處理數據源) 有這種經歷的人都知道,讓後端改接口這是一個很不現實方案,尤爲是對於三端(web、andriod、ios)公用同一套後端接口的狀況下, 讓後端改接口的結構基本不可能,因此通常都是前端本身作一些接口數據的適配工做

其實咱們真的很但願, 咱們須要什麼數據,須要什麼格式,後端就按照什麼格式給咱們返回什麼樣的數據結構,咱們要哪些字段,後端就只給咱們返回咱們須要的這些字段, 其餘的都不返回,這樣,前端就和後端解耦了,咱們不用再天天和後端由於接口問題去撕逼,GraphQL就是一個這樣的思路來幫助咱們解決這個先後端聯調接口的問題, 在前端直接寫查詢, 後端只管給前端返回前端查詢的這些數據;前端

2. 還有一種場景:

一個頁面裏展現的信息, info1, info2, info3,前端須要請求多個接口,info1對應的接口A中的a字段,info2對應的接口B中的b字段,info3對應的接口C中的c字段java

// /api/user/A
{
    id: 1111,
    name: '張三',
    a: '當前頁面要展現的info1',
    b: 'b'
    // 其餘字段
}
// /api/order/B
{
    id: 2222,
    name: 'hahah',
    a: 'a'
    b: '當前頁面要展現的info2',
    // 其餘字段
}
// /api/system/C
{
    id: 3333,
    name: 'hehe',
    a: 'a'
    c: '當前頁面要展現的info3',
    // 其餘字段
}
複製代碼

這個時候,稍微有點脾氣的前端,都會去找後端撕逼,node

前端A: 「就這三個字段,你還讓我請求三個接口,你不能一個接口都返回給我嗎」, 後端B:「哎, 我也想啊,可是xxxxx, 因此我這邊很差改,」, ... 最後那就這樣吧。ios

固然,我舉得這個例子是一個很簡單的場景,實際開發過程當中要比這個還要複雜;git

若是使用GraphQL的話,前端本身寫查詢,這個頁面須要哪些需哪數據,後端就返回給哪些數據, 這是考慮到後端全部的接口都在同一個域下面,可是通常比較複雜的系統,後端都會分爲不一樣的域, 用戶域,商品域,基礎模塊域,交易域等等,這時即便用了GraphQL也可能github

後端C:「你看其餘都不是我負責的域,我要是本身給你封裝一個,我本身底層須要通過xxxxx等複雜的步驟去獲取其餘域的,這個很複雜, 你仍是直接去他哪一個域去查詢吧」,web

有兩種方法,express

  • 你就再多寫一個GraphQL
  • 本身寫一個node中間層,中間層來處理這些接口數據的聚合,換句話說,中間層來聚合成一個GraphQL查詢來返回給前端, 中間層分別取調用服務端的三個接口,而後把三個接口返回的數據聚合成前端所須要的

GraphQL一個簡單的入門示例

準備

npm i --save express  express-graphql graphql cors
複製代碼

服務端代碼

var express = require('express');
var graphqlHTTP = require('express-graphql');
const { buildSchema } = require('graphql');
const cors = require('cors'); // 用來解決跨域問題

// 建立 schema,須要注意到:
// 1. 感嘆號 ! 表明 not-null
// 2. rollDice 接受參數
const schema = buildSchema(` type Query { username: String age: Int! } `)
const root = {
    username: () => {
        return '李華'
    },
    age: () => {
        return Math.ceil(Math.random() * 100)
    },
}
const app = express();
app.use(cors());
app.use('/graphql', graphqlHTTP({
    schema: schema,
    rootValue: root,
    graphiql: true
}))

app.listen(3300);
console.log('Running a GraphQL API server at http://localhost:3300/graphql')
複製代碼

客戶端代碼

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>graphql demo</title>
</head>

<body>
    <button class="test">獲取當前用戶數據</button>
    <p class="username"></p>
    <p class="age"></p>
</body>
<script> var test = document.querySelector('.test'); test.onclick = function () { var username = document.querySelector('.username'); var age = document.querySelector('.age'); fetch('http://localhost:3300/graphql', { headers: { 'Content-Type': 'application/json', 'Accept': 'application/json' }, method: 'POST', body: JSON.stringify({ query: `{ username, age, }` }), mode: 'cors' // no-cors, cors, *same-origin }) .then(function (response) { return response.json(); }) .then(function (res) { console.log('返回結果', res); username.innerHTML = `姓名:${res.data.username}`; age.innerHTML = `年齡:${res.data.age}` }) .catch(err => { console.error('錯誤', err); }); } </script>

</html>
複製代碼

運行結果

graphql

源碼地址

參考

相關文章
相關標籤/搜索