[英]GDAX API - Rate limit exceeded
I get an error message saying "Rate limit exceeded" when I try to request historical data from GDAX. 当我尝试从GDAX请求历史数据时,收到一条错误消息“超出速率限制”。 I use promises and setInterval to request historical price data from GDAX like this:
我使用promise和setInterval从GDAX请求历史价格数据,如下所示:
let promiseArray = //Array with promises
let j = 0;
let grabPrices = setInterval(() => {
if (j === promiseArray.length) {
//Do something when all promises have been resolved
}
else {
promiseArray[j].then(
data => {
//Work with data
}
).catch(error => console.log('An error occurred: ' + error));
j++;
}
}, 1000) //I have even tried to use 10 seconds (10000) as a second argument to setInterval, but it doesn't make any difference.
FROM the official API documentation 从官方API文档
Rate Limits When a rate limit is exceeded, a status of 429 Too Many Requests will be returned. 速率限制超过速率限制时,将返回429个请求过多的状态。
REST API PUBLIC ENDPOINTS We throttle public endpoints by IP: 3 requests per second, up to 6 requests per second in bursts. REST API公共端点我们通过IP限制公共端点:每秒3个请求,每秒最多6个请求。
When you have a promise then the request is already made so your promiseArray is an array of ongoing requests. 当您有一个Promise时,该请求已经发出,因此您的promiseArray是一个正在进行的请求的数组。
Let's say I have an array of urls and use fetch
to get the content. 假设我有一个网址数组,并使用
fetch
来获取内容。 Using map
to map the url to a promise and give the array of promises to Promise.all
: 使用
map
将URL映射到一个Promise.all
数组提供给Promise.all
:
Promise.all(
urls.map(fetch)
).then(
resulst=>...
);
If urls has 10 items this program will make 10 requests immediately. 如果网址有10个项目,则此程序将立即发出10个请求。
You can pass the fetch
function to a throttle function that will schedule fetch in such a way that it will only be called 3 times a second. 您可以将
fetch
函数传递给节流函数,该函数将以每秒仅调用3次的方式调度获取。 The throttle function will return a promise but will not call fetch immediately. 节流功能将返回一个Promise,但不会立即调用fetch。
The throttlePeriod function can be found here . 节流阀功能可以在这里找到。 If you're only going to copy paste code from that module and not import the whole module then you need the later function as well because throttlePeriod depends on it.
如果您只打算从该模块复制粘贴代码而不导入整个模块,那么您还需要后面的函数,因为节流阀取决于它。
const fetchMaxThreePerSecond = throttlePeriod(3,1100)/*give it an extra 100*/(fetch)
Promise.all(
urls.map(fetchMaxThreePerSecond)
).then(
resulst=>...
);
That takes care of the throttling but if you know how Promise.all
works you know that all promises reject if only one rejects. 这可以解决节流问题,但是如果您知道
Promise.all
工作原理,那么您就会知道,只有一个拒绝,所有的Promise.all
都会被拒绝。 So if you have a hundred urls and 99 resolve but one rejects your .then
never gets called. 因此,如果您有100个网址和99个解析地址,但其中一个拒绝了您的
.then
不会被调用。 You will loose the 99 successful requests. 您将丢失99个成功的请求。
You could pass a promise to Promise.all
that will not reject, you can do so by catching a rejected promise and in the catch return a special value that you can filter out when processing results: 您可以将一个承诺传递给
Promise.all
所有不会拒绝的承诺都可以通过捕获被拒绝的承诺来实现,并在catch中返回一个特殊的值,您可以在处理结果时过滤掉该值:
const fetchMaxThreePerSecond = throttlePeriod(3,1100)/*give it an extra 100*/(fetch);
const Fail = function(reason){this.reason = reason;};
const isFail = x=>(x&&x.constructor)===Fail;
const isNotFail = x=>!isFail(x);
Promise.all(
urls.map(
url=>
fetchMaxThreePerSecond(url)
.catch(e=>new Fail([url,e]))//save url and error in Fail object
)
)
.then(//even if a request fails, it will not reject
results=>{
const successes = results.filter(isNotFail);
const failed = results.filter(isFail);
if(failed.length!==0){
console.log("some requests failed:");
failed.forEach(
(fail)=>{
const [url,error] = fail.reason;
console.log(`Url: ${url}`);
console.log(JSON.stringify(error,undefined,2));
}
)
}
}
);
I have no problem with GDAX history calls when I set my rate limiter to 3 API calls every 2.1 seconds. 将速率限制器设置为每2.1秒3个API调用时,GDAX历史记录调用没有问题。
I have some occasional problems when I set my rate limiter to 3 API calls every 1.8 seconds. 当我将速率限制器设置为每1.8秒3个API调用时,偶尔会遇到一些问题。
I have tested these values with automated tests. 我已经用自动化测试测试了这些值。
Important: all my calls to GDAX share the same rate limiter(!) 重要提示:我对GDAX的所有呼叫均使用相同的速率限制器(!)
To be save, use the code from @HMR's answer together with my tested parameters. 为保存起见,请使用@HMR答案中的代码以及我测试过的参数。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.