本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。
解析器
從前面的章節中,您瞭解結構描述和資料來源的元件。現在,我們需要解決結構描述和資料來源的互動方式。這一切都始於解析器。
解析器是一種代碼單元,用於處理向服務發出請求時如何解析該字段的數據。解析器附加到模式中類型中的特定字段。它們最常用於實現查詢,突變和訂閱字段操作的狀態更改操作。解析器將處理客戶端的請求,然後返回結果,它可以是一組輸出類型,如對象或標量:
![](images/aws-flow-infographic.png)
解析器運行時
在中AWS AppSync,您必須先指定解析程式的執行階段。解析器運行時指示在其中執行解析器的環境。它還規定了您的解析器將使用的語言。 AWS AppSync目前支援用於 JavaScript 和速度範本語言 (VTL) 的應用程式 SYNC_JS。請參閱 VTL 的解析器和函數的JavaScript 運行時功能 JavaScript 或解析器映射模板實用程序參考。
解析器結構
代碼方面,解析器可以通過幾種方式進行構造。有單元和管道解析器。
單位解析器
單元解析器由定義針對數據源執行的單個請求和響應處理程序的代碼組成。請求處理程序將上下文對象作為參數,並返回用於調用數據源的請求有效負載。響應處理程序從數據源接收有效負載,並帶有執行請求的結果。回應處理常式會將有效負載轉換成 GraphQL 回應,以解析 GraphQL 欄位。
![](images/unit-resolver-js.png)
管道解析器
在實施管道解析器時,它們遵循一個通用的結構:
-
在步驟之前:當客戶端提出請求時,正在使用的模式字段(通常是您的查詢,突變,訂閱)的解析器將傳遞請求數據。解析器將開始使用 before step 處理程序處理請求數據,這允許在數據通過解析器移動之前執行一些預處理操作。
-
函數(S):在步驟運行之前,請求被傳遞到函數列表。清單中的第一個函數會針對資料來源執行。函數是解析器代碼的子集,其中包含自己的請求和響應處理程序。請求處理器將採取請求數據並針對數據源執行操作。響應處理程序將數據源的響應傳遞回列表之前處理數據源的響應。如果有多個函數,請求數據將被發送到要執行的列表中的下一個函數。列表中的函數將按照開發人員定義的順序進行連續執行。一旦所有的函數都被執行,最終的結果被傳遞給後一步。
-
之後步驟:之後的步驟是一個處理函數,允許您在將其傳遞給 GraphQL 響應之前對最終函數的響應執行一些最終操作。
![](images/appsync-js-resolver-logic.png)
解析程式處理程式結構
處理程序通常是調用Request
和的函數Response
:
export function request(ctx) { // Code goes here } export function response(ctx) { // Code goes here }
在單元解析器中,只有一組這些功能。在管道解析器中,將有一組用於步驟之前和之後的步驟和每個函數的附加集合。為了可視化這看起來如何,讓我們回顧一個簡單的Query
類型:
type Query { helloWorld: String! }
這是一個簡單的查詢,其中包含一個名為 type helloWorld
的字段String
。讓我們假設我們總是希望這個字段返回字符串「Hello World」。為了實現這種行為,我們需要將解析器添加到此字段中。在單元解析器中,我們可以添加如下所示的內容:
export function request(ctx) { return {} } export function response(ctx) { return "Hello World" }
request
可以保留空白,因為我們沒有請求或處理數據。我們也可以假設我們的數據源是None
,表明此代碼不需要執行任何調用。響應只是返回「你好世界」。為了測試這個解析器,我們需要使用查詢類型的請求:
query helloWorldTest { helloWorld }
這是一個名為helloWorldTest
返回helloWorld
字段的查詢。執行時,字helloWorld
段解析器也會執行並返回響應:
{ "data": { "helloWorld": "Hello World" } }
像這樣返回常量是你可以做的最簡單的事情。實際上,您將返回輸入,列表等。這是一個更複雜的例子:
type Book { id: ID! title: String } type Query { getBooks: [Book] }
在這裡,我們返回的列表Books
。假設我們使用 DynamoDB 資料表來儲存書籍資料。我們的處理程序可能如下所示:
/** * Performs a scan on the dynamodb data source */ export function request(ctx) { return { operation: 'Scan' }; } /** * return a list of scanned post items */ export function response(ctx) { return ctx.result.items; }
我們的請求使用內置的掃描操作來搜索表中的所有條目,將發現項目存儲在上下文中,然後將其傳遞給響應。響應採取的結果項,並在響應中返回它們:
{ "data": { "getBooks": { "items": [ { "id": "abcdefgh-1234-1234-1234-abcdefghijkl", "title": "book1" }, { "id": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee", "title": "book2" }, ... ] } } }
解析器上下文
在解析器中,處理程序鏈中的每個步驟都必須知道先前步驟中數據的狀態。來自一個處理程序的結果可以被存儲並作為參數傳遞給另一個處理程序。GraphQL 定義了四個基本的解析器參數:
解析器基本參數 | 描述 |
---|---|
obj 、root 、parent 等等 |
父項的結果。 |
args |
提供給 GraphQL 查詢中欄位的引數。 |
context |
提供給每個解析器並保存重要的上下文信息,例如當前登錄的用戶或訪問數據庫的值。 |
info |
保存與當前查詢相關的字段特定信息以及模式詳細信息的值。 |
在中AWS AppSync,context
(ctx) 引數可以容納上述所有資料。它是每個請求創建的對象,包含諸如授權憑據,結果數據,錯誤,請求元數據等數據。上下文是程序員操縱來自請求其他部分的數據的簡單方法。再次採取這個片段:
/** * Performs a scan on the dynamodb data source */ export function request(ctx) { return { operation: 'Scan' }; } /** * return a list of scanned post items */ export function response(ctx) { return ctx.result.items; }
該請求被賦予上下文(ctx)作為參數; 這是請求的狀態。它對表中的所有項目執行掃描,然後將結果存儲回中的上下文中result
。然後,上下文會傳遞至回應引數,該引數會存取result
並傳回其內容。
請求和解析
當您對 GraphQL 服務進行查詢時,它必須先執行剖析和驗證程序,才能執行。您的請求將被解析並轉換為抽象語法樹。樹的內容是透過針對您的結構描述執行多種驗證演算法來驗證。驗證步驟後,樹的節點遍歷和處理。調用解析器,結果存儲在上下文中,並返回響應。例如,採取以下查詢:
query { Person { //object type name //scalar age //scalar } }
我們正在返回Person
與name
和age
欄位。運行此查詢時,樹將如下所示:
![](images/ast-1.png)
從樹狀結構中,這個要求會在結構描述Query
中搜尋根目錄。在查詢內部,該Person
字段將被解析。從前面的例子中,我們知道這可能是來自用戶的輸入,值列表等Person
很可能與包含我們需要的字段的對象類型相關聯(name
和age
)。一旦找到這兩個子字段,它們將按給定的順序(name
後跟age
)進行解析。一旦樹狀結構完全解決,請求就會完成並傳送回用戶端。