[譯] 怎樣使用GraphQL - 進階 - 2.服務端

英文原版地址:https://www.howtographql.com/...前端

GraphQL一般被認爲是前端的API技術,由於它使客戶端可以以更好的方式獲取數據。 可是既然是API,固然是在服務器端實現的。 由於GraphQL使服務器開發人員可以專一於描述數據,而不是實現和優化特定的接口,因此在服務器上也有不少好處。git

GraphQL執行

GraphQL經過定義Schema和查詢語言,來從Schema中檢索數據,但卻不只僅是這一種方式。更是一種實際的執行算法,用於將這些查詢轉換爲結果。 該算法的核心很是簡單:查詢逐字段遍歷,爲每一個字段執行「解析器」。 讓假設咱們有如下模式:github

type Query {
  author(id: ID!): [Author]
}

type Author {
  posts: [Post]
}

type Post {
  title: String
  content: String
}

下面是咱們使用該Schema發送到服務器的查詢:算法

query {
  author(id: "abc") {
    posts {
      title
      content
    }
  }
}

首先要關注的是查詢中的每一個字段均可以與一個類型相對應:數據庫

query: Query {
  author(id: "abc"): Author {
    posts: [Post] {
      title: String
      content: String
    }
  }
}

如今,咱們能夠輕鬆地找到並運行服務器中每一個字段對應的解析器。從查詢類型開始執行,並之外層爲先。這意味着咱們先運行Query.author的解析器。而後,咱們將該解析器的結果傳遞給它的子解析器,Author.posts的解析器。在下一級,結果是一個列表,在這種狀況下,算法會依次在每一個元素上執行一次。因此最終執行工做以下:後端

Query.author(root, { id: 'abc' }, context) -> author
Author.posts(author, null, context) -> posts
for each post in posts
  Post.title(post, null, context) -> title
  Post.content(post, null, context) -> content

最終,執行算法將全部結果數據正確的放在定義好的結構中,並返回。
須要注意的是,大多數GraphQL服務器實現將提供「默認解析器」 - 所以您沒必要爲每一個單個字段指定解析器函數。例如,在GraphQL.js中,當解析器的父對象包含具備正確名稱的字段時,不須要指定解析器。
在Apollo博客上的「GraphQL Explained「文章中,可更深刻的瞭解GraphQL執行狀況。服務器

批量解析

你可能會注意到上述執行策略的一件事是,它有點幼稚。例如,若是你有從後端API或數據庫提取的解析器,則在執行一個查詢期間可能會屢次調用該後端。讓咱們假設,咱們想獲取幾個帖子的做者,就像這樣:函數

query {
  posts {
    title
    author {
      name
      avatar
    }
  }
}

若是這些是博客上的帖子,極可能不少帖子將有相同的做者。因此若是咱們須要一個API調用來獲取每一個做者對象,咱們可能會意外地爲同一個對象發出多個請求。例如:工具

fetch('/authors/1')
fetch('/authors/2')
fetch('/authors/1')
fetch('/authors/2')
fetch('/authors/1')
fetch('/authors/2')

咱們如何解決這個問題?讓咱們聰明一點。咱們能夠將fetch函數封裝在一個工具函數中,該實函數將等待全部的解析器運行後,再確保只fetch每一個元素一次:post

authorLoader = new AuthorLoader()

// Queue up a bunch of fetches
authorLoader.load(1);
authorLoader.load(2);
authorLoader.load(1);
authorLoader.load(2);

// Then, the loader only does the minimal amount of work
fetch('/authors/1');
fetch('/authors/2');

咱們能作得更好嗎?固然,若是咱們的API支持批量請求,咱們只能對後端執行一次提取操做,以下所示:

fetch('/authors?ids=1,2')

這也能夠封裝在上面的工具函數中。
在JavaScript中,可使用 DataLoader 的工具實現上述策略,其餘語言也有相似的工具。

相關文章
相關標籤/搜索