简体   繁体   English

GDAX API-超出了速率限制

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM