GraphQL 初體驗(yàn):GraphQL + Node.js

GraphQL 是什么

GraphQL is a query language created by Facebook in 2012 which provides a common interface between the client and the server for data fetching and manipulations.

The client asks for various data from the GraphQL server via queries. The response format is described in the query and defined by the client instead of the server: they are called client‐specified queries. The structure of the data is not hardcoded as in traditional REST APIs - this makes retrieving data from the server more efficient for the client.

GraphQL 是 Facebook 開(kāi)發(fā)的一個(gè)應(yīng)用層的數(shù)據(jù)查詢語(yǔ)言颅筋。通過(guò) GraphQL慨亲,客戶端可以從服務(wù)端的數(shù)據(jù)集中輕松獲得一個(gè)自定義結(jié)構(gòu)的數(shù)據(jù)。


假設(shè)某個(gè)業(yè)務(wù)需要以下數(shù)據(jù)內(nèi)容 a:

{
  user(id: 3500401) {
    id,
    name,
    isViewerFriend
  }
}

沒(méi)錯(cuò)晋渺,這不是 json,但我們?nèi)匀豢梢钥炊硎镜氖遣樵?id 為 3500401 用戶的 idnameisViewerFriend 信息稍刀。

用戶信息對(duì)于各個(gè)業(yè)務(wù)都是通用的,假設(shè)另外一個(gè)業(yè)務(wù)需要這樣的用戶信息 b:

{
  user(id: 3500401) {
    name,
    profilePicture(size: 50)  {
      uri,
      width,
      height
    }
  }
}

一般來(lái)說(shuō)敞曹,用戶信息對(duì)應(yīng)的數(shù)據(jù)模型都是固定的,每次請(qǐng)求其實(shí)就是對(duì)數(shù)據(jù)做過(guò)濾和篩選综膀。對(duì)應(yīng)到數(shù)據(jù)庫(kù)操作澳迫,就是數(shù)據(jù)的查詢操作。如果客戶端也能夠發(fā)送“查詢”請(qǐng)求剧劝,那不就可以從后端接口這個(gè)大的“數(shù)據(jù)集”中去過(guò)濾篩選業(yè)務(wù)所需要的數(shù)據(jù)了嗎橄登?

GraphQL 就是基于這樣的思想來(lái)設(shè)計(jì)的。上面提到的(a)和(b)類(lèi)型的數(shù)據(jù)結(jié)構(gòu)就是 GraphQL 的查詢內(nèi)容讥此。使用上面的查詢拢锹,GraphQL 服務(wù)器會(huì)分別返回如下響應(yīng)內(nèi)容。

a 查詢對(duì)應(yīng)的響應(yīng):

{
  "user" : {
    "id": 3500401,
    "name": "Jing Chen",
    "isViewerFriend": true
  }
}

b 查詢對(duì)應(yīng)的響應(yīng):

{
  "user" : {
    "name": "Jing Chen",
    "profilePicture": {
      "uri": "http: //someurl.cdn/pic.jpg",
      "width": 50,
      "height": 50
    }
  }
}

只需要改變查詢內(nèi)容萄喳,前端就能定制服務(wù)器返回的響應(yīng)內(nèi)容卒稳,這就是 GraphQL 的客戶端指定查詢(Client Specified Queries)。

實(shí)現(xiàn) GraphQL 服務(wù)器

第一步:

  • 創(chuàng)建工程目錄 hello-graphql
  • 初始化項(xiàng)目他巨,以及引入所需的包
npm init -f
npm install graphql express express-graphql --save
npm install babel-cli babel-preset-es2015 --save-dev
npm install -g nodemon

第二步:
在項(xiàng)目根目錄下創(chuàng)建 data 目錄充坑,并在該目錄下創(chuàng)建 data.json 文件减江,并輸入以下內(nèi)容:

{
    "1": {
        "id": "1",
        "name": "Dan"
    },
    "2": {
        "id": "2",
        "name": "Marie"
    },
    "3": {
        "id": "3",
        "name": "Jessie"
    }
}

第三步:
創(chuàng)建 server.js 文件,并輸入以下內(nèi)容:

import express from 'express'

const app = express()
const port = 3000

app.get('/', (req, res) => {
    res.send('Hello!');
});

let server = app.listen(port, function () {
    let addr = server.address();
    let bind = typeof addr === 'string' ? 'pipe ' + addr : 'port ' + addr.port;
    console.log('Listening on ' + bind);
});

命令行運(yùn)行:nodemon --exec babel-node --presets=es2015 server.js捻爷,瀏覽器輸入:http://localhost:3000 辈灼。顯示 Hello!,說(shuō)明你的 express 服務(wù)已經(jīng) OK 了也榄。

第四步:
創(chuàng)建文件夾 /src/schema巡莹,并創(chuàng)建文件 index.js。并在 index.js 文件中編寫(xiě)GraphQL Schema甜紫。Schema 是 GraphQL 請(qǐng)求的入口榕莺,用戶請(qǐng)求的
GraphQL 將會(huì)對(duì)應(yīng)到具體的 Schema。

import {
    GraphQLObjectType,
    GraphQLSchema,
    GraphQLString,
    GraphQLInt
} from 'graphql'

// 我們要用的模擬數(shù)據(jù)
const data = require('../../data/data.json')

const User = new GraphQLObjectType({
    name: 'User',
    description: 'User對(duì)象',
    fields: {
        id: {
            type: GraphQLInt
        },
        name: {
            type: GraphQLString
        },
    }
});

const Query = new GraphQLObjectType({
    name: 'Query',
    fields: {
        user: {
            type: User,
            args: {
                id: {
                    type: GraphQLInt
                }
            },
            resolve: function (_, args) {
                return data[args.id];
            }
        }
    }
});

const Schema = new GraphQLSchema({
    query: Query
});

export default Schema;

第五步:
修改 server.js 文件棵介,連接 schema钉鸯。將 server.js 文件修改為以下內(nèi)容:

import express from 'express'
import Schema from './src/schema'
import graphqlHTTP from 'express-graphql'

const app = express()
const port = 3000

app.use('/', graphqlHTTP({
    schema: Schema,
    graphiql: true
}));

let server = app.listen(port, function () {
    var addr = server.address();
    var bind = typeof addr === 'string' ? 'pipe ' + addr : 'port ' + addr.port;
    console.log('Listening on ' + bind);
});

這時(shí),在瀏覽器中可以查看到如下界面:

在左邊的空白處輸入:

{
  user(id: 1) {
    name
  }
}

點(diǎn)擊“運(yùn)行”按鈕邮辽,右邊會(huì)出現(xiàn)結(jié)果:

{
  "data": {
    "user": {
      "name": "Dan"
    }
  }
}
總結(jié)

至此唠雕,我們已經(jīng)搭建好了簡(jiǎn)單的 GraphQL 服務(wù)器。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末吨述,一起剝皮案震驚了整個(gè)濱河市岩睁,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌揣云,老刑警劉巖捕儒,帶你破解...
    沈念sama閱讀 217,509評(píng)論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異邓夕,居然都是意外死亡刘莹,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,806評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門(mén)焚刚,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)点弯,“玉大人,你說(shuō)我怎么就攤上這事矿咕∏栏兀” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,875評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵碳柱,是天一觀的道長(zhǎng)捡絮。 經(jīng)常有香客問(wèn)我,道長(zhǎng)莲镣,這世上最難降的妖魔是什么福稳? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,441評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮剥悟,結(jié)果婚禮上灵寺,老公的妹妹穿的比我還像新娘曼库。我一直安慰自己,他們只是感情好略板,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,488評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布毁枯。 她就那樣靜靜地躺著,像睡著了一般叮称。 火紅的嫁衣襯著肌膚如雪种玛。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,365評(píng)論 1 302
  • 那天瓤檐,我揣著相機(jī)與錄音赂韵,去河邊找鬼。 笑死挠蛉,一個(gè)胖子當(dāng)著我的面吹牛祭示,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播谴古,決...
    沈念sama閱讀 40,190評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼质涛,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了掰担?” 一聲冷哼從身側(cè)響起汇陆,我...
    開(kāi)封第一講書(shū)人閱讀 39,062評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎带饱,沒(méi)想到半個(gè)月后毡代,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,500評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡勺疼,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,706評(píng)論 3 335
  • 正文 我和宋清朗相戀三年教寂,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片恢口。...
    茶點(diǎn)故事閱讀 39,834評(píng)論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡孝宗,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出耕肩,到底是詐尸還是另有隱情,我是刑警寧澤问潭,帶...
    沈念sama閱讀 35,559評(píng)論 5 345
  • 正文 年R本政府宣布猿诸,位于F島的核電站,受9級(jí)特大地震影響狡忙,放射性物質(zhì)發(fā)生泄漏梳虽。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,167評(píng)論 3 328
  • 文/蒙蒙 一灾茁、第九天 我趴在偏房一處隱蔽的房頂上張望窜觉。 院中可真熱鬧谷炸,春花似錦、人聲如沸禀挫。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,779評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)语婴。三九已至描孟,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間砰左,已是汗流浹背匿醒。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,912評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留缠导,地道東北人廉羔。 一個(gè)月前我還...
    沈念sama閱讀 47,958評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像僻造,于是被迫代替她去往敵國(guó)和親憋他。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,779評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容