GraphQL入門有這一篇就足夠了

本文將從GraphQL是什么伟众,為什么要使用GraphQL理张,使用GraphQL創(chuàng)建簡單例子赫蛇,以及GraphQL實戰(zhàn),四個方面對GraphQL進(jìn)行闡述雾叭。說得不對的地方悟耘,希望大家指出斧正。

github項目地址:https://github.com/Charming2015/graphql-todolist

一织狐、GraphQL是什么?

關(guān)于GraphQL是什么暂幼,網(wǎng)上一搜一大堆筏勒。根據(jù)官網(wǎng)的解釋就是一種用于 API 的查詢語言。

一看到用于API的查詢語言旺嬉,我也是一臉懵逼的管行。博主你在開玩笑吧?你的翻譯水平不過關(guān)邪媳?API還能查嗎捐顷?API不是后端寫好,前端調(diào)用的嗎雨效?

的確可以套菜,這就是GraphQL強(qiáng)大的地方。
引用官方文檔的一句話:

ask exactly what you want.

二、為什么要使用GraphQL?

在實際工作中往往會有這種情景出現(xiàn):比如說我需要展示一個游戲名的列表,可接口卻會把游戲的詳細(xì)玩法夫啊,更新時間遮晚,創(chuàng)建者等各種各樣的 (無用的) 信息都一同返回。

問了后端渣蜗,原因大概如下:

原來是為了兼容PC端和移動端用同一套接口
或者在整個頁面屠尊,這里需要顯示游戲的標(biāo)題,可是別的地方需要顯示游戲玩法啊耕拷,避免多次請求我就全部返回咯
或者是因為有時候項目經(jīng)理想要顯示“標(biāo)題+更新時間”讼昆,有時候想要點擊標(biāo)題展開游戲玩法等等需求,所以把游戲相關(guān)的信息都一同返回

簡單說就是:

   * 兼容多平臺導(dǎo)致字段冗余
   * 一個頁面需要多次調(diào)用 API 聚合數(shù)據(jù)
    * 需求經(jīng)常改動導(dǎo)致接口很難為單一接口精簡邏輯

有同學(xué)可能會說那也不一定要用GraphQL啊骚烧,比方說第一個問題浸赫,不同平臺不同接口不就好了嘛

http://api.xxx.com/web/getGameInfo/:gameID
http://api.xxx.com/app/getGameInfo/:gameID
http://api.xxx.com/mobile/getGameInfo/:gameID

或者加個參數(shù)也行

http://api.xxx.com/getGameInfo/:gameID?platfrom=web

這樣處理的確可以解決問題,但是無疑加大了后端的處理邏輯赃绊。你真的不怕后端程序員打你既峡?

這個時候我們會想,接口能不能不寫死碧查,把靜態(tài)變成動態(tài)运敢?

回答是可以的,這就是GraphQL所做的!

三忠售、GraphQL嘗嘗鮮——(GraphQL簡單例子)

下面是用GraphQL.js和express-graphql搭建一個的普通GraphQL查詢(query)的例子传惠,包括講解GraphQL的部分類型和參數(shù),已經(jīng)掌握了的同學(xué)可以跳過稻扬。

  1. 先跑個hello world

新建一個graphql文件夾卦方,然后在該目錄下打開終端,執(zhí)行npm init --y初始化一個packjson文件泰佳。
安裝依賴包:npm install --save -D express express-graphql graphql
新建sehema.js文件愿汰,填上下面的代碼

//schema.js
const {
      GraphQLSchema,
      GraphQLObjectType,
      GraphQLString,
    } = require('graphql');
const queryObj = new GraphQLObjectType({
    name: 'myFirstQuery',
    description: 'a hello world demo',
    fields: {
        hello: {
            name: 'a hello world query',
            description: 'a hello world demo',
            type: GraphQLString,
            resolve(parentValue, args, request) {
                return 'hello world !';
            }
        }
    }
});
module.exports = new GraphQLSchema({
  query: queryObj
});

這里的意思是新建一個簡單的查詢困后,查詢名字叫hello,會返回字段hello world !衬廷,其他的是定義名字和查詢結(jié)果類型的意思摇予。

同級目錄下新建server.js文件,填上下面的代碼

// server.js
const express = require('express');
const expressGraphql = require('express-graphql');
const app = express();

const schema = require('./schema');
app.use('/graphql', expressGraphql({
    schema,
    graphiql: true
}));

app.get('/', (req, res) => res.end('index'));

app.listen(8000, (err) => {
  if(err) {throw new Error(err);}
  console.log('*** server started ***');
});

這部分代碼是用express跑起來一個服務(wù)器吗跋,并通過express-graphql把graphql掛載到服務(wù)器上侧戴。

運行一下node server,并打開http://localhost:8000/

圖片.png

如圖跌宛,說明服務(wù)器已經(jīng)跑起來了
打開http://localhost:8000/graphql酗宋,是類似下面這種界面說明已經(jīng)graphql服務(wù)已經(jīng)跑起來了!
這里寫圖片描述

在左側(cè)輸入 (graphql的查詢語法這里不做說明)

{
  hello
}

點擊頭部的三角形的運行按鈕疆拘,右側(cè)就會顯示你查詢的結(jié)果了


這里寫圖片描述
2. 不僅僅是hello world

先簡單講解一下代碼:

const queryObj = new GraphQLObjectType({
    name: 'myFirstQuery',
    description: 'a hello world demo',
    fields: {}
});

GraphQLObjectType是GraphQL.js定義的對象類型蜕猫,包括name、description 和fields三個屬性哎迄,其中name和description 是非必填的回右。fields是解析函數(shù),在這里可以理解為查詢方法

hello: {
            name: 'a hello world query',
            description: 'a hello world demo',
            type: GraphQLString,
            resolve(parentValue, args, request) {
                return 'hello world !';
            }
        }

對于每個fields漱挚,又有name翔烁,description,type旨涝,resolve參數(shù)蹬屹,這里的type可以理解為hello方法返回的數(shù)據(jù)類型,resolve就是具體的處理方法白华。

說到這里有些同學(xué)可能還不滿足慨默,如果我想每次查詢都想帶上一個參數(shù)該怎么辦,如果我想查詢結(jié)果有多條數(shù)據(jù)又怎么處理弧腥?

下面修改schema.js文件业筏,來一個加強(qiáng)版的查詢(當(dāng)然,你可以整理一下代碼鸟赫,我這樣寫是為了方便閱讀)

const {
      GraphQLSchema,
      GraphQLObjectType,
      GraphQLString,
      GraphQLInt,
      GraphQLBoolean
    } = require('graphql');

const queryObj = new GraphQLObjectType({
    name: 'myFirstQuery',
    description: 'a hello world demo',
    fields: {
        hello: {
            name: 'a hello world query',
            description: 'a hello world demo',
            type: GraphQLString,
            args: {
                name: {  // 這里定義參數(shù)蒜胖,包括參數(shù)類型和默認(rèn)值
                    type: GraphQLString,
                    defaultValue: 'Brian'
                }
            },
            resolve(parentValue, args, request) { // 這里演示如何獲取參數(shù),以及處理
                return 'hello world ' + args.name + '!';
            }
        },
        person: {
            name: 'personQuery',
            description: 'query a person',
            type: new GraphQLObjectType({ // 這里定義查詢結(jié)果包含name,age,sex三個字段抛蚤,并且都是不同的類型台谢。
                name: 'person',
                fields: {
                  name: {
                    type: GraphQLString
                  },
                  age: {
                    type: GraphQLInt
                  },
                  sex: {
                    type: GraphQLBoolean
                  }
                }
            }),
            args: {
                name: {
                    type: GraphQLString,
                    defaultValue: 'Charming'
                }
            },
            resolve(parentValue, args, request) {
                return {
                    name: args.name,
                    age: args.name.length,
                    sex: Math.random() > 0.5
                };
            }
        }
    }
});

module.exports = new GraphQLSchema({
  query: queryObj 
});

重啟服務(wù)后,繼續(xù)打開http://localhost:8000/graphql岁经,在左側(cè)輸入

{
  hello(name:"charming"),
  person(name:"charming"){
    name,
    sex,
    age
  }
}

右側(cè)就會顯示出:


圖片.png

你可以在左側(cè)僅輸入person方法的sex和age兩個字段朋沮,這樣就會只返回sex和age的信息。動手試一試吧!

{
  person(name:"charming"){
    sex,
    age
  }
}

當(dāng)然,結(jié)果的順序也是按照你輸入的順序排序的樊拓。

定制化的數(shù)據(jù)纠亚,完全根據(jù)你查什么返回什么結(jié)果。這就是GraphQL被稱作API查詢語言的原因筋夏。

四蒂胞、GraphQL實戰(zhàn)

下面我將搭配koa實現(xiàn)一個GraphQL查詢的例子,逐步從簡單koa服務(wù)到mongodb的數(shù)據(jù)插入查詢条篷,再到GraphQL的使用骗随,最終實現(xiàn)用GraphQL對數(shù)據(jù)庫進(jìn)行增刪查改。

項目效果大概如下:

20180905142957816.gif

有點意思吧赴叹?那就開始吧~
先把文件目錄建構(gòu)建好

  1. 初始化項目

    初始化項目鸿染,在根目錄下運行npm init --y,
    然后安裝一些包:npm install koa koa-static koa-router koa-bodyparser --save -D
    新建config乞巧、controllers涨椒、graphql、mongodb绽媒、public蚕冬、router這幾個文件夾。裝逼的操作是在終端輸入mkdir config controllers graphql mongodb public router回車些椒,ok~

  2. 跑一個koa服務(wù)器
    新建一個server.js文件,寫入以下代碼

// server.js
import Koa from 'koa'
import Router from 'koa-router'
import bodyParser from 'koa-bodyparser'

const app = new Koa()
const router = new Router();
const port = 4000

app.use(bodyParser());

router.get('/hello', (ctx, next) => {
  ctx.body="hello world"
});


app.use(router.routes())
   .use(router.allowedMethods());

app.listen(port);

console.log('server listen port: ' + port)

這里的意思是新建一個簡單的查詢掸刊,查詢名字叫hello免糕,會返回字段hello world !,其他的是定義名字和查詢結(jié)果類型的意思忧侧。

同級目錄下新建server.js文件石窑,填上下面的代碼

// server.js
const express = require('express');
const expressGraphql = require('express-graphql');
const app = express();

const schema = require('./schema');
app.use('/graphql', expressGraphql({
    schema,
    graphiql: true
}));

app.get('/', (req, res) => res.end('index'));

app.listen(8000, (err) => {
  if(err) {throw new Error(err);}
  console.log('*** server started ***');
});

這部分代碼是用express跑起來一個服務(wù)器,并通過express-graphqlgraphql掛載到服務(wù)器上蚓炬。

  1. 運行一下node server松逊,并打開http://localhost:8000/
這里寫圖片描述

如圖,說明服務(wù)器已經(jīng)跑起來了
打開http://localhost:8000/graphql肯夏,是類似下面這種界面說明已經(jīng)graphql服務(wù)已經(jīng)跑起來了经宏!

圖片.png

在左側(cè)輸入 (graphql的查詢語法這里不做說明)

{
  hello
}

點擊頭部的三角形的運行按鈕,右側(cè)就會顯示你查詢的結(jié)果了


圖片.png
  1. 不僅僅是hello world

先簡單講解一下代碼:

const queryObj = new GraphQLObjectType({
    name: 'myFirstQuery',
    description: 'a hello world demo',
    fields: {}
});

GraphQLObjectType是GraphQL.js定義的對象類型驯击,包括name徊都、description 和fields三個屬性主之,其中name和description 是非必填的槽奕。fields是解析函數(shù)枉长,在這里可以理解為查詢方法

hello: {
            name: 'a hello world query',
            description: 'a hello world demo',
            type: GraphQLString,
            resolve(parentValue, args, request) {
                return 'hello world !';
            }
        }

對于每個fields,又有name吼蚁,description肝匆,type,resolve參數(shù)能曾,這里的type可以理解為hello方法返回的數(shù)據(jù)類型,resolve就是具體的處理方法驼唱。

說到這里有些同學(xué)可能還不滿足玫恳,如果我想每次查詢都想帶上一個參數(shù)該怎么辦,如果我想查詢結(jié)果有多條數(shù)據(jù)又怎么處理?

下面修改schema.js文件审孽,來一個加強(qiáng)版的查詢(當(dāng)然式散,你可以整理一下代碼,我這樣寫是為了方便閱讀)

const {
      GraphQLSchema,
      GraphQLObjectType,
      GraphQLString,
      GraphQLInt,
      GraphQLBoolean
    } = require('graphql');

const queryObj = new GraphQLObjectType({
    name: 'myFirstQuery',
    description: 'a hello world demo',
    fields: {
        hello: {
            name: 'a hello world query',
            description: 'a hello world demo',
            type: GraphQLString,
            args: {
                name: {  // 這里定義參數(shù)乖篷,包括參數(shù)類型和默認(rèn)值
                    type: GraphQLString,
                    defaultValue: 'Brian'
                }
            },
            resolve(parentValue, args, request) { // 這里演示如何獲取參數(shù),以及處理
                return 'hello world ' + args.name + '!';
            }
        },
        person: {
            name: 'personQuery',
            description: 'query a person',
            type: new GraphQLObjectType({ // 這里定義查詢結(jié)果包含name,age,sex三個字段鲸沮,并且都是不同的類型。
                name: 'person',
                fields: {
                  name: {
                    type: GraphQLString
                  },
                  age: {
                    type: GraphQLInt
                  },
                  sex: {
                    type: GraphQLBoolean
                  }
                }
            }),
            args: {
                name: {
                    type: GraphQLString,
                    defaultValue: 'Charming'
                }
            },
            resolve(parentValue, args, request) {
                return {
                    name: args.name,
                    age: args.name.length,
                    sex: Math.random() > 0.5
                };
            }
        }
    }
});

module.exports = new GraphQLSchema({
  query: queryObj 
});

重啟服務(wù)后,繼續(xù)打開http://localhost:8000/graphql毕荐,在左側(cè)輸入

{
  hello(name:"charming"),
  person(name:"charming"){
    name,
    sex,
    age
  }
}

右側(cè)就會顯示出:


圖片.png

你可以在左側(cè)僅輸入person方法的sex和age兩個字段员寇,這樣就會只返回sex和age的信息蝶锋。動手試一試吧!

{
  person(name:"charming"){
    sex,
    age
  }
}

當(dāng)然,結(jié)果的順序也是按照你輸入的順序排序的躯舔。

定制化的數(shù)據(jù)粥庄,完全根據(jù)你查什么返回什么結(jié)果布讹。這就是GraphQL被稱作API查詢語言的原因描验。

四睡扬、GraphQL實戰(zhàn)

參考:https://blog.csdn.net/qq_41882147/article/details/82966783

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末阐枣,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子蔼两,更是在濱河造成了極大的恐慌甩鳄,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,948評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件额划,死亡現(xiàn)場離奇詭異妙啃,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)俊戳,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,371評論 3 385
  • 文/潘曉璐 我一進(jìn)店門揖赴,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人抑胎,你說我怎么就攤上這事燥滑。” “怎么了阿逃?”我有些...
    開封第一講書人閱讀 157,490評論 0 348
  • 文/不壞的土叔 我叫張陵铭拧,是天一觀的道長赃蛛。 經(jīng)常有香客問我,道長搀菩,這世上最難降的妖魔是什么焊虏? 我笑而不...
    開封第一講書人閱讀 56,521評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮秕磷,結(jié)果婚禮上诵闭,老公的妹妹穿的比我還像新娘。我一直安慰自己澎嚣,他們只是感情好疏尿,可當(dāng)我...
    茶點故事閱讀 65,627評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著易桃,像睡著了一般褥琐。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上晤郑,一...
    開封第一講書人閱讀 49,842評論 1 290
  • 那天敌呈,我揣著相機(jī)與錄音,去河邊找鬼造寝。 笑死磕洪,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的诫龙。 我是一名探鬼主播析显,決...
    沈念sama閱讀 38,997評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼签赃!你這毒婦竟也來了谷异?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,741評論 0 268
  • 序言:老撾萬榮一對情侶失蹤锦聊,失蹤者是張志新(化名)和其女友劉穎歹嘹,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體孔庭,經(jīng)...
    沈念sama閱讀 44,203評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡尺上,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,534評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了史飞。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片尖昏。...
    茶點故事閱讀 38,673評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡仰税,死狀恐怖构资,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情陨簇,我是刑警寧澤吐绵,帶...
    沈念sama閱讀 34,339評論 4 330
  • 正文 年R本政府宣布迹淌,位于F島的核電站,受9級特大地震影響己单,放射性物質(zhì)發(fā)生泄漏唉窃。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,955評論 3 313
  • 文/蒙蒙 一纹笼、第九天 我趴在偏房一處隱蔽的房頂上張望纹份。 院中可真熱鬧,春花似錦廷痘、人聲如沸蔓涧。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,770評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽元暴。三九已至,卻和暖如春兄猩,著一層夾襖步出監(jiān)牢的瞬間茉盏,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,000評論 1 266
  • 我被黑心中介騙來泰國打工枢冤, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留鸠姨,地道東北人。 一個月前我還...
    沈念sama閱讀 46,394評論 2 360
  • 正文 我出身青樓淹真,卻偏偏與公主長得像享怀,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子趟咆,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,562評論 2 349