Egg.js中使用GraphQL-簡單實戰

GraphQL實戰

1. GrqphQL是什麼

GraphQL是一種面向數據的API查詢風格。javascript

GraphQL是由Facebook主導開發的一款面向數據的API查詢語言。客戶端只需給他一個描述,而後GraphQL就能從數據庫組合出符合描述的數據並返回。前端

2. GraphQL解決了什麼問題

在開發中咱們通常都使用的是RESTful API,它是是面向資源的。一般渲染一個頁面咱們須要多個資源,REST API請求多個資源時就會載入多個URL,而GraphQL能夠經過一次請求就能夠獲取到須要的全部數據。java

解決痛點:數據庫

  • 接口返回數據格式並非調用者(前端)理想型npm

  • 多個資源只用一個請求,減小服務器壓力json

  • 數據字段由調用者控制後端

GraphQL 既是一種用於 API 的查詢語言也是一個知足你數據查詢的運行時。 GraphQL 對你的 API 中的數據提供了一套易於理解的完整描述,使得客戶端可以準確地得到它須要的數據,並且沒有任何冗餘,也讓 API 更容易地隨着時間推移而演進,還能用於構建強大的開發者工具。數組

示例:瀏覽器

這裏以掘金的首頁舉例,它可能分爲這幾個資源(文章列表,分類列表,做者榜)bash

REST API

文章列表/articles

[
    {
        title: 'xxx',
        content: 'xxx內容'
    }
]
複製代碼

分類列表/categories

[
	{
		id: '1'
		name: '前端',
	},
	{
		id: '2'
		name: '後端',
	},
]
複製代碼

做者推薦榜/recommendationAuthor

[
    {
        id: 1,
        username: '張三'
    }
]
複製代碼

上面是用REST接口來獲取首頁須要的數據,須要發送3次請求,再看下GraphQL的請求是什麼樣?

GraphQL查詢接口/graphql/query

query getHomePage() {
	articleList($first: 0) {
		title
        content
    },
    categoryList(){
        id
        name
    },
    recommendationAuthorList($limit: 10) {
        id
        username
    },
      
} 
複製代碼

經過Graphql只用請求一次就能夠拿到所有信息,返回的數據格式都是由調用者控制的,很少很多。

3 GraphQL重要概念

這裏先介紹幾個GraphQL比較重要的概念,能夠參考着GraphQL官網文檔看。

3.1 操做類型

操做類型能夠是query、mutation、substription ,描述你打算作什麼類型的操做。

  1. query 查詢
  2. mutation 變動
  3. substription 訂閱,當數據更新後,會推送消息

每個Graphql都有一個query類型,也可能有一個mutation類型。他們定義了每個Graphql查詢的入口。

3.2 標量類型

  • Int 有符號32位整數
  • Float 有符號雙精度浮點數
  • String UTF-8字符序列
  • Boolean true或者false
  • ID ID標量類型標識一個惟一標識符

3.3 對象類型和字段

type Article{
	title: String
	author: [User]
}
複製代碼

上面我聲明瞭一個GraphQL對象類型,這裏聲明瞭兩個字段並指定了字段類型。

String是內置的標量類型之一,查詢中沒法對他進行次級選擇。

[User] 表示一個User數組,數組中的每一個項目都是一個User對象。

  • User對象怎麼來的呢?

    如Article同樣 使用type關鍵字聲明

    type User {
    	name: String
    	age: Int
    }
    複製代碼
  • 聲明對象有什麼用?

    經過Query對外提供查詢入口時,咱們一般都是以一個對象爲一個單位。能夠把每一個對象看做成一個接口。

3.3 輸入類型

經過Mutation對外提供變動入口。有時你須要傳遞一整個對象做爲新建對象,以前的標量類型就不能知足了。

官網示例:

4. egg-graphql實戰

客戶端使用前,咱們須要在服務端定義Schema結構。

4.1 使用腳手架生成Egg項目

PS: 下載太慢時能夠先全局安裝egg-init腳手架,再執行egg-init --type simple --registry china使用淘寶鏡像生成項目

4.2 安裝graphql插件

  1. 執行npm i egg-apollo-server --save

  2. 在egg項目中添加graphql的相關配置, 詳見egg-apollo-server

​ 這裏我沒有用egg-graphql插件而使用的是egg-apollo-server

PS:config.graphql.subscriptions用來對grapql請求作鑑權的,在此demo裏不須要改成false便可

4.3 定義schema

├── app
│   ├── controller
│   │   └── home.js
│   ├── graphql
│   │   ├── article
│   │   │   ├── resolver.js
│   │   │   └── schema.graphql
│   ├── router.js
│   └── service
├── config
│   ├── config.default.js
│   └── plugin.js
├── package.json
└── package-lock.json
複製代碼
  • schema.graphql

    定義GraphQL類型和操做

    extend type Query {
        articleList(first: ID): [Article]
    }
    
    type Article {
        id: ID
        title: String
        content: String
        author: Author
    }
    type Author {
        name: String
        age: Int
    }
    
    extend type Mutation {
        addArticle(title: String, content: String, author: AddAuthor): Article
    }
    
    input AddArticle {
        title: String
        content: String
    }
    
    input AddAuthor {
        name: String
        age: Int
    }
    複製代碼
  • resolver.js

    實現操做

    'use strict';
    const list = [
      {
        id: 1,
        content: 'aaa',
        title: '',
        author: {
          name: 'aaa',
          age: 18,
        },
      },
      {
        id: 2,
        content: 'bbb',
        title: '',
        author: {
          name: 'aaa',
          age: 18,
        },
      },
    ];
    module.exports = {
      Query: {
        articleList: () => {
          return list;
        },
    
      },
      Mutation: {
        addArticle(root, params, ctx) {
          console.log(params);
          params.id = list.length++;
          list.push(params);
          return params;
        },
      },
    };
    
    複製代碼

4.4 graphql調試

瀏覽器打開 http://127.0.0.1:7001/graphql進行調試

PS: 測試前須要關閉csrf保護,不然調試發送的post請求將會被攔截

左側爲查詢區,在這裏寫操做語句。右側爲執行結果。

查詢調試

{
  articleList(first: 0){
    id
    title
    content
    author{
			name
      age
    }
	}
}
複製代碼

變動調試

mutation {
  addArticle(title: "title", content: "content", author: {name: "張三", age: 15}){
    title
    content
    id
  }
}
複製代碼
相關文章
相關標籤/搜索