以优雅的方式将GraphQL变量传递给第二个函数
我正在使用GraphQL,在找到将变量从查询传递到结果的最佳方法时遇到了一些困难 我有这样一个模式:以优雅的方式将GraphQL变量传递给第二个函数,graphql,Graphql,我正在使用GraphQL,在找到将变量从查询传递到结果的最佳方法时遇到了一些困难 我有这样一个模式: type Fragment { # The id of the fragment id: String! # The key of the fragment key: String! # The type of component component_type: String! # The params used to build the fragment params
type Fragment {
# The id of the fragment
id: String!
# The key of the fragment
key: String!
# The type of component
component_type: String!
# The params used to build the fragment
params: JSON
# Component data
data: JSON
children: [JSON]
items: [JSON]
}
该片段表示为“cms”片段。我想在这个问题解决后将一些查询数据传递到另一个后端
我的查询如下所示:
query getFragmentsWithItems($keys: [String!]!
$platform: PlatformType
$version: String
$userInfo: UserInput
$userId: Int
) {
fragmentsWithItems(keys: $keys, platform: $platform, version: $version, userInfo: $userInfo, userId: $userId) {
key
data
children
params
items
}
}
问题是:我在片段的data
字段中有一些查询数据。在解析该片段之前,该数据不可用。我想把数据发送到另一个后端。我想用GraphQL来做这件事,我希望做一些类似的事情:
Fragment: () => {
async query(obj, args, context, info, {modles}) => {
const items = await models.getItems(obj.query_string);
}
}
type Fragment {
items: ItemSearchResult(user_info: UserInput) etc
但是我需要传递给原始查询的user\u info
和user\u id
。显然,这只能从info
参数中访问,而该参数并不打算使用
我采用的另一种方法是使用手动解析器,它可以执行以下操作:
const resolveFI = ({ keys, platform, version, userInfo, userId, models }) => {
if (!keys || !keys.length) {
return Promise.resolve(null);
}
return models.release.get({ platform, version }).then(release =>
Promise.all(
keys.map(key =>
models.fragments.get({
key,
platform,
version,
release: release.id
})
)
).then(data => {
const promises = [];
data.rows.forEach(r => {
if (r.data.query_data) {
const d = {
// Can just ignore
filters: r.data.query_data.filters || {},
user_info: userInfo,
user_id: userId
};
promises.push(
new Promise(resolve => {
resolve(
models.itemSearch.get(d).then(i => ({ items: i.items, ...r }))
);
})
);
}
...etc other backends
这是可行的,但是手动承诺链似乎无法达到使用GraphQL的目的
我最后尝试的是将项
设置为非标量类型,类似于:
Fragment: () => {
async query(obj, args, context, info, {modles}) => {
const items = await models.getItems(obj.query_string);
}
}
type Fragment {
items: ItemSearchResult(user_info: UserInput) etc
但由于我无法将实际结果从片段传输到无法工作的ItemSearchResult
我意识到这相当冗长,所以我愿意接受编辑或澄清。
我想看看我是否错过了一个更好的方法,或者我是否应该把它打包,让客户端应用程序在取回片段数据后进行项目查询。这并不是说你不应该使用信息
——这只是使用起来的巨大痛苦;)说真的,它是用来优化和更高级的用例的,所以如果没有更好的解决方案,你应该毫不犹豫地使用它。有一些库()可以用来更容易地解析对象
也就是说,我认为有几种方法可以解决这个问题:
1.)在查询解析器内
不幸的是,如果有许多不同的查询返回片段,那么最终将导致冗余
2.)片段类型上现有字段(或附加字段)的解析程序内部
如果您走这条路线,并且需要将参数传递到查询字段,则可以使用info提取这些参数。或者,您也可以在查询解析器中改变上下文对象,并将这些参数附加到它。然后,查询解析器“下面”的所有解析器(如片段字段的解析器)都可以通过上下文访问这些参数
3.)Apollo Server允许您在配置其中间件时定义formatResponse
函数。这本质上提供了一个钩子,在响应返回到客户端之前,可以对响应执行任何操作。您可以解析该函数内的响应,并从该函数调用另一个后端。您说“我想获取该数据并将其发送到另一个后端”--您是否试图通过调用另一个API来解析项
字段,或者您只是想将部分查询结果发布到另一个后端?第二个后端。我想把我从查询片段中得到的东西发布到items后端。谢谢你的评论和详细信息。因为我没有修改info
,所以我认为这是最好的解决方法。我按回车键太快了,我想这就是我一直在寻找的东西。它保留原始参数,直到其中一个解析器返回“undefined”。