我正在使用 apollo-link-rest 构建对免费 3rd 方 rest api 的调用。 我认为这是一个很好的用例。
但是,众所周知,就请求并发性和连续 api 请求之间的最小安全差距而言,应以_尊重的方式处理第 3 方 api。 即确保您访问服务器的频率不超过每 100 毫秒。
当阿波罗接管电话时,我想知道是否有一种很好的方法可以随着时间的推移分散电话? 偶然地,创建一个触发额外请求来解决完整请求的查询并不需要太多时间。 例如通过使用@export
指令。
_一次打两个电话_🚀🚀
const QUERY = gql`
query RestData($email: String!) {
# 1) Query for user 🚀
users @rest(path: '/users/email?{args.email}', method: 'GET', type: 'User') {
id @export(as: "id")
firstName
lastName
# 2) Sub query for friends fires immediately as well 🚀
friends @rest(path: '/friends/{exportVariables.id}', type: '[User]') {
firstName
lastName
}
}
}
`;
为了减轻n+1 查询问题的轻情况(即获取所有产品,而不是每个产品描述),我希望能够为服务器 429 错误(由于服务器的速率限制而失败)提供安全网。
_我现在在做什么:包装提取_
const restProviders = new RestLink({
endpoints: {
mySlowEndpoint: baseUrl
},
customFetch: (...args) =>
new Promise((resolve, reject) => {
// 🚙⟷🚕⟷🚗 Implementing my queue logic to fire of fetches
resolve(fetch(...args));
// when enough time has elapsed. 🚙⟷🚕⟷🚗
})
})
现在我正在将获取过程包装在自定义队列逻辑中,但是有没有一种“更优雅的方式”可以集成它? 我敢肯定,很多人都会有兴趣对传出负载进行一些控制,而不必立即使查询失败。
也许我应该为来自谷歌的其他人添加我现在所做的事情。 现在我使用p-throttle
( repo )。
// (...)
import pThrottle from "p-throttle";
const restProviders = new RestLink({
endpoints: {
mySlowEndpoint: baseUrl
},
// Throttle fetches to max 1 concurrent request 🚀 and
// min. delay of 0.5 seconds 🚙⟷🚕⟷🚗 .
customFetch: pThrottle( (...args) => {
return fetch(...args);
}, 1, 500)
})
// (...)
@D1no我打算建议 customFetch,但您已经这样做了!
我不确定这是否真的应该是 Apollo-link-rest 的直接可配置功能,但我支持在文档中包含这样的片段。
你能指出我在文档中的一个好地方来公关这个信息作为一个例子可以用 customFetch 做什么吗? 我想你是对的; 将这样的可配置性扔到 apollo-link-rest 中会结合 fetch 方法,这不是很优雅。
在 PR 中,我会踢出 p-queue 为新手阅读的更人为的例子。 任何认真使用 apollo-link-rest 作为进入 GraphQL 的网关药物的人都会在某个时候需要_一些并发/去抖动管理_。
嘿@D1no ,你可以在这里找到文档。 我建议它应该位于Options
标题中,高于Complete options
。
谢谢@tombarton。 再次仔细研究这个问题,无论如何,为 fetch 调用提供一个简单的节流选项可能是个好主意。
虽然我最初说的是它的耦合获取,但实际上并非如此。 它对(任何任意)获取方法的调用在这里猖獗。 为了能够盲目地/急切地执行 apollo-link-rest,一些简单的并发和 ms 限制选项,如上所示,最终可能不是一个坏主意。
const restProviders = new RestLink({
endpoints: {
mySlowEndpoint: baseUrl
},
maxConcurrency: 2 // Max Concurrency 🚀🚀
minThrottle: 500 // Handling Rate Limit in ms 🚙⟷🚕⟷🚗
})
和/或能够在查询中指定它
const QUERY = gql`
query RestData($email: String!) {
users @rest(path: '/users/email?{args.email}', method: 'GET', type: 'User') {
id @export(as: "id")
firstName
lastName
# NEW: ⤥ 🚙⟷🚕 ⤥ 🚀🚀
friends @rest(throttle: 500, concurrency: 2, path: '/friends/{exportVariables.id}', type: '[User]') {
firstName
lastName
}
}
}
`;
毕竟,为什么 fetch 方法要管理它被调用的频率(它不应该关心楼上发生了什么)。 我会考虑一下。 无论如何, customFetch
应该传递一些关于当前查询的信息,而不仅仅是一个空白请求(如果人们真的需要,能够做出明智的决定)。
也许其中一位维护人员/员工(@fbartho)可以参与进来? 如果它的优点被批准,我很乐意花时间进行 PR。
@D1no老实说,我很喜欢您将其包含在文档中的建议。 -- 排队与我们希望在我们公司的应用程序中做事的方式相反。 (例如,重复数据删除是我构建的一种)。
另外,由于端点可能完全不同,我不愿将“maxConcurrency/minThrottle”设置为全局关注点。
ApolloLinkRest 是关于“将东西插入 Apollo”——你一直在描述的这些问题真的觉得它们应该在网络层,也就是自定义获取。 -- 此外,我发现您不太可能希望为每个查询路径自定义这些值,因此将它们的设置嵌入到 GraphQL 中似乎很嘈杂。
好的 - 我将首先对文档进行 PR 补充。 我们应该先将customFetch
触底,然后再在它上面涂抹一层。
最有用的评论
也许我应该为来自谷歌的其他人添加我现在所做的事情。 现在我使用
p-throttle
( repo )。