天天看點

GraphQL的JavaScript實作graphql-js應用舉例

GraphQL的JavaScript實作graphql-js應用舉例

系列文章:

<a href="https://segmentfault.com/a/1190000006132986">graphql 核心概念</a>

graphql-js 淺嘗(本文)

常言道,實踐是檢驗真理的唯一标準。

上一篇文章講了 graphql 的核心概念,所提到的一些例子都是理論化的,并沒有實際代碼做支撐,就好像在畫一個大餅,總是讓人不那麼信服。

它真的有那麼神奇嗎?那就同我一起看下去,用事實說話。

之前那篇文章一直有提到 graphql 是一個概念,每個語言可以有自己實作它的方式。因為,我是搞前端的,對 javascript 比較熟悉,是以,這裡就用 graphql-js(graphql 的 javascript 實作)來舉例。

hello world

遵循傳統,第一個例子必須是 hello world。

首先,安裝就不用多說了。

npm install graphql-js --save 

那這個例子該怎麼設計哪?假設,查詢一個 hello 字元串,就傳回一個 world 字元串,很明顯 type 的結構就該是這樣

type helloworld { 

hello: string 

如何實作這個 helloworld 類型哪?graphql-js 已經定義好了基礎類,我們直接調用就行。那麼,這個 type 實作起來也就非常簡單了

import { 

    graphqlstring, 

    graphqlobjecttype, 

} from 'graphql'; 

const helloworldtype = new graphqlobjecttype({ 

    name: 'helloworldtype', 

    fields: () =&gt; ({ 

        hello: { 

            type: graphqlstring, 

        } 

    }) 

}); 

簡單分析一下上面的代碼,可以看到 helloworldtype 是一個 graphqlobjecttype 的執行個體,它包含一個 fields 是 hello,這個 hello 所對應的傳回類型是字元串。

那如何傳回 world 字元串?那就給它個 resolve 方法

            resolve() { 

                return 'world'; 

            }, 

這樣類型就定義好了,還記不記得上篇文章提到的類型定義完成後該怎麼辦?

對,建立查詢的 schema。

    graphqlschema, 

    fields: { 

    } 

const schema = new graphqlschema({ 

    query: helloworldtype 

schema 設定好了,是不是想查詢看看哪?

GraphQL的JavaScript實作graphql-js應用舉例

東風當然是伺服器啦。graphql 官方提供 express-graphql 這個中間件來支援基于 graphql 的查詢,是以,這裡選用 express 作為伺服器。

安裝就不再重複了,隻需将剛剛建立的 schema 添加到 express 的中間件中就可以了。

const app = express(); 

app 

    .use('/graphql', graphqlhttp({ schema, pretty: true })) 

    .listen(3000, () =&gt; { 

        console.log('graphql server running on http://localhost:3000/graphql'); 

    }); 

當當當當~完成,去 postman 裡查詢 http://localhost:3000/graphql?query={hello} 看看吧。

blog system

在上一篇文章裡,我們設計了一個部落格的查詢 schema,這次我們就來動手實作它。(下面就開始講例子啦,不願聽我唠叨的可以直接看代碼)

前面 helloworld 的例子講的比較詳細,現在大家熟悉了文法,接下來的案例就會過得快一些。

首先是 posttype,這裡對 posttype 做了一點小修改,給幾個字段添加了不能為空的設計。

/** 

 * type post { 

 *   id: id!, 

 *   name: string!, 

 *   createdate: string!, 

 *   title: string!, 

 *   subtitle: string, 

 *   content: string, 

 *   tags: [tag] 

 * } 

 */ 

const post = new graphqlobjecttype({ 

    name: 'posttype', 

        id: { 

            type: new graphqlnonnull(graphqlid) 

        }, 

        name: { 

            type: new graphqlnonnull(graphqlstring) 

        createdate: { 

        title: { 

        subtitle: { 

            type: graphqlstring 

        content: { 

        tags: { 

            type: new graphqllist(tagtype), 

            resolve: post =&gt; post.tags.map(tagname =&gt; gettagbyname(tagname)) 

然後是另一個主要的 type: tag type。

 * type tag { 

 *   label: string!, 

 *   posts: [post] 

const tag = new graphqlobjecttype({ 

    name: 'tagtype', 

        label: { 

        posts: { 

            type: new graphqllist(posttype), 

            resolve: tag =&gt; getpostslist().filter(post =&gt; ~post.tags.indexof(tag.name)) 

兩個主要的類型已經定義好了,把它們倆整合起來就是部落格類型了。

 * type blog { 

 *   post: post,    // 查詢一篇文章 

 *   posts: [post],    // 查詢一組文章,用于部落格首頁 

 *   tag: tag,        // 查詢一個标簽 

 *   tags: [tag],    // 查詢所有标簽,用于部落格标簽頁 

const blogtype = new graphqlobjecttype({ 

    name: 'blogtype', 

        post: { 

            type: posttype, 

            args: { 

                name: { 

                    type: graphqlstring 

                } 

            resolve: (blog, { name }) =&gt; getpostbyname(name), 

            resolve: () =&gt; getpostslist(), 

        tag: { 

            type: tagtype, 

            resolve: (blog, { name }) =&gt; gettagbyname(name), 

            resolve: () =&gt; gettagslist(), 

這裡有一個新東西,就是 arg 字段,用來擷取查詢參數,如果在沒有設定過 arg 字段的屬性上添加變量進行查詢,graphql-js 的驗證系統會報錯。

最後,将之前的 helloworld 類型稍微修飾一下,獨立出來,然後和 blog type 整合到一起成為根查詢類。

const querytype = new graphqlobjecttype({ 

    name: 'rootquerytype', 

        hello: worldtype, 

        blog: { 

            type: blogtype, 

            resolve: () =&gt; ({}) 

    query: querytype 

ok。這樣整個 demo 就完成了(檢視源碼戳這裡),快去 postman 試試各種查詢,體驗 graphql 的神奇吧。(不知道怎麼寫查詢語句的就看上一篇吧)

GraphQL的JavaScript實作graphql-js應用舉例

最後

如果,你不喜歡 get 方法或查詢字元串過長,express-graphql 也支援 post 方法,伺服器會先檢視請求的 url

中是否包含查詢字元串,如果不包含就會去 request body 中擷取,隻需在 request header 中将 content-type

設定為 application/graphql 就可以了。

全文一直在說查詢,或許你會疑惑,那我修改怎麼做哪?graphql 中的修改稱之為 mutation。mutation

可以定義自己的接口解析類,它在 graphql 的 schema 中是一個可選項,其他的和查詢并無兩樣,隻是最後在 resolve

方法中的處理方式不同而已。

    query: querytype, 

    mutation: mutationtype 

最後的最後提一句,nodemon 很好用,誰用誰知道。

作者:discipled

來源:51cto

繼續閱讀