【问题标题】:GDAX API - Rate limit exceededGDAX API - 超出速率限制
【发布时间】:2018-02-03 03:16:41
【问题描述】:

当我尝试从 GDAX 请求历史数据时,我收到一条错误消息“超出速率限制”。我使用 promises 和 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.

来自official API documentation

速率限制 超过速率限制时,将返回 429 Too Many Requests 状态。

REST API 公共端点 我们通过 IP 限制公共端点:每秒 3 个请求,突发最多每秒 6 个请求。

【问题讨论】:

    标签: javascript api gdax-api


    【解决方案1】:

    当你有一个承诺时,请求已经发出,所以你的 promiseArray 是一个正在进行的请求的数组。

    假设我有一个 url 数组并使用 fetch 来获取内容。使用map 将url 映射到一个promise 并将promise 数组赋予Promise.all

    Promise.all(
      urls.map(fetch)
    ).then(
      resulst=>...
    );
    

    如果 urls 有 10 个项目,此程序将立即发出 10 个请求。

    您可以将fetch 函数传递给节流函数,该函数将以每秒仅调用 3 次的方式调度获取。油门函数将返回一个承诺,但不会立即调用 fetch。

    throttlePeriod 函数可以在here 找到。如果您只想从该模块复制粘贴代码而不导入整个模块,那么您还需要 later 函数,因为throttlePeriod 依赖于它。

    const fetchMaxThreePerSecond = throttlePeriod(3,1100)/*give it an extra 100*/(fetch)
    Promise.all(
      urls.map(fetchMaxThreePerSecond)
    ).then(
      resulst=>...
    );
    

    这可以解决节流问题,但是如果您知道 Promise.all 的工作原理,您就会知道如果只有一个拒绝,所有承诺都会拒绝。因此,如果您有 100 个 url 和 99 个解析但一个拒绝您的 .then 永远不会被调用。您将丢失 99 个成功的请求。

    您可以向Promise.all 传递一个不会拒绝的承诺,您可以通过捕获被拒绝的承诺并在捕获中返回一个特殊值,您可以在处理结果时将其过滤掉:

    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));
            }
          )
        }
      }
    ); 
    

    【讨论】:

    • 这太棒了。谢谢。
    【解决方案2】:

    当我将速率限制器设置为每 2.1 秒 3 次 API 调用时,我对 GDAX 历史调用没有任何问题。

    当我将速率限制器设置为每 1.8 秒 3 次 API 调用时,我偶尔会遇到一些问题。

    我已经用自动化测试测试了这些值。

    重要提示:我对 GDAX 的所有调用共享相同的速率限制器(!)

    要保存,请将@HMR 答案中的代码与我测试的参数一起使用。

    【讨论】:

      猜你喜欢
      • 2012-08-10
      • 2018-08-27
      • 2019-05-23
      • 2011-12-22
      • 1970-01-01
      • 1970-01-01
      • 2017-02-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多