GraphQL 徹底改變了我們獲取和塑造資料的方式,在客戶端和伺服器之間提供了一個乾淨的抽象層。它的核心功能之一是解析器,它允許我們定義模式中的每個欄位如何取得其資料。在某些情況下,開發人員可能會透過依賴解析器中的實用方法無意中削弱 GraphQL 的優勢。這種做法不僅違背了 GraphQL 的設計初衷,還引入了不必要的複雜性和潛在的 bug。
讓我們深入探討為什麼會出現這個問題以及如何做得更好。
在 GraphQL 中,會為類型的每個實例呼叫解析器,無論類型出現在架構中的位置。這種抽象確保了解析資料的邏輯在整體上保持一致。例如:
schema { query: Query } type Query { project(id: ID!): Project user(id: ID!): User } type Project { id: ID! name: String! owner: User! } type User { id: ID! name: String! email: String! }
這裡,User 類型在兩個地方使用:直接在 Query 中用於獲取用戶,以及作為所有者嵌套在 Project 類型中。借助 GraphQL 的解析器系統,我們可以定義單一 User 解析器來處理 User 欄位的解析方式,確保 User 出現的任何地方的行為一致。
當您引入實用方法來在解析器之外塑造資料時,您就打破了這種抽象。考慮這個例子:
// utils.ts function mapToUser(userData: DataSourceUser) { return { id: userData.id, name: userData.full_name, email: userData.contact_email, }; } // resolvers.ts const resolvers: Resolvers<Context> = { Query: { project: async (_, { id }, { dataSources }) => { const project = await dataSources.projectAPI.getProject(id); return { ...project, owner: mapToUser(project.owner), // Utility method called here }; }, user: async (_, { id }, { dataSources }) => { const user = await dataSources.userAPI.getUser(id); return mapToUser(user); // Utility method called here }, }, };
乍一看,這似乎沒問題。但這就是它有問題的原因:
您被迫在出現使用者類型的每個解析器中呼叫mapToUser。忘記呼叫它或錯誤地呼叫它可能會導致 API 中的行為不一致。
GraphQL 的解析器系統旨在集中解決每種類型的方式。透過使用實用程式方法,您可以迴避此功能並使您的程式碼不太直觀。
如果您需要修改使用者類型的解析方式(例如,新增欄位或處理錯誤),您將必須尋找呼叫 mapToUser 的每個位置,而不是更新單一解析器。
不要使用實用方法,而是為 GraphQL 類型定義解析器。以下是重寫上面範例的方法:
schema { query: Query } type Query { project(id: ID!): Project user(id: ID!): User } type Project { id: ID! name: String! owner: User! } type User { id: ID! name: String! email: String! }
在解析器中使用實用方法似乎是一種捷徑,但它最終會破壞 GraphQL 的強大功能和優雅性。透過為您的類型定義解析器,您可以維護一個乾淨、一致且可擴展的 API。因此,停止在解析器中使用 utils,擁抱 GraphQL 提供的抽象化——未來的你會感謝你的!
以上是為什麼應該避免 GraphQL 解析器中的實用方法的詳細內容。更多資訊請關注PHP中文網其他相關文章!