如何在Apollo Federation中处理同类型不同解析逻辑的字段?
可行实现方案
方案1:通过实体解析器传递上下文标识
调用方子图在解析content的text2和text3字段时,给对应的test实体携带不同的标识参数,被调用方子图根据这个标识执行不同处理逻辑。
调用方子图代码示例:
const resolvers = { Content: { text2: (parent) => { // 返回test实体,附带逻辑标识A return { id: parent.text2Id, handlerType: 'A' }; }, text3: (parent) => { // 返回test实体,附带逻辑标识B return { id: parent.text3Id, handlerType: 'B' }; } }, Test: { __resolveReference: (reference) => { // 将标识传递给被调用方子图 return dataSources.testAPI.fetchTest(reference.id, reference.handlerType); } } };
被调用方子图代码示例:
const resolvers = { Test: { __resolveReference: (reference) => { const { handlerType } = reference; if (handlerType === 'A') { // 执行逻辑A:比如从特定数据源获取数据或做专属处理 return logicA(reference.id); } else if (handlerType === 'B') { // 执行逻辑B:不同的数据源或处理规则 return logicB(reference.id); } // 默认 fallback 逻辑 return defaultHandler(reference.id); }, // 也可以在具体字段解析器中区分逻辑 name: (parent) => { if (parent.handlerType === 'A') { return getAName(parent.id); } return getBName(parent.id); } } };
方案2:拆分实体类型(业务划分更清晰)
如果text2和text3对应的业务逻辑差异较大,可以把通用的test拆分为两个独立实体类型,比如TestA和TestB,被调用方子图直接为不同实体实现专属解析逻辑,避免上下文判断的复杂度。
调用方子图修改后的Schema:
type Content { text2: TestA text3: TestB } type TestA @key(fields: "id") { id: String } type TestB @key(fields: "id") { id: String }
被调用方子图修改后的Schema:
type TestA @key(fields: "id") { id: String name: String code: String } type TestB @key(fields: "id") { id: String name: String code: String }
被调用方子图解析器:
const resolvers = { TestA: { __resolveReference: (reference) => { // 直接执行逻辑A return logicA(reference.id); } }, TestB: { __resolveReference: (reference) => { // 直接执行逻辑B return logicB(reference.id); } } };
方案3:利用自定义指令标记字段
在调用方子图的Schema中给text2和text3添加自定义指令,解析时提取指令信息传递给被调用方,以此区分处理逻辑。
调用方子图Schema:
directive @handler(type: String!) on FIELD_DEFINITION type Content { text2: test @handler(type: "A") text3: test @handler(type: "B") } type test @key(fields: "id") { id: String }
调用方子图解析器传递指令信息:
const resolvers = { Content: { text2: (parent, _, __, info) => { // 提取字段上的handler指令参数 const handlerType = info.fieldNodes[0].directives.find(d => d.name.value === 'handler')?.arguments[0].value.value; return { id: parent.text2Id, handlerType }; }, text3: (parent, _, __, info) => { const handlerType = info.fieldNodes[0].directives.find(d => d.name.value === 'handler')?.arguments[0].value.value; return { id: parent.text3Id, handlerType }; } } };
被调用方子图处理逻辑:
和方案1的被调用方逻辑一致,根据传递的handlerType执行对应逻辑即可。
内容的提问来源于stack exchange,提问作者Raven
相关产品推荐
相关产品推荐

