GDAX API - превышен лимит
При попытке запросить исторические данные у GDAX появляется сообщение об ошибке "Превышен лимит скорости". Я использую обещания и 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.
ОТ официальной документации API
Ограничения скорости Когда предел скорости превышен, будет возвращен статус 429 Too Many Requests.
ПУБЛИЧНЫЕ РАЗДЕЛЕНИЯ API REST Мы ограничиваем общедоступные конечные точки по IP: 3 запроса в секунду, до 6 запросов в секунду в пакетах.
2 ответа
Когда у вас есть обещание, тогда запрос уже сделан, поэтому ваш блок обещаний представляет собой массив текущих запросов.
Допустим, у меня есть массив URL-адресов и использовать fetch
чтобы получить контент. С помощью map
сопоставить URL с обещанием и дать массив обещаний Promise.all
:
Promise.all(
urls.map(fetch)
).then(
resulst=>...
);
Если в URL-адресе 10 пунктов, эта программа немедленно отправит 10 запросов.
Вы можете передать fetch
Функция для функции газа, которая будет планировать выборку таким образом, что она будет вызываться только 3 раза в секунду. Функция газа вернет обещание, но не вызовет fetch немедленно.
Функция throttlePeriod находится здесь. Если вы собираетесь только скопировать код вставки из этого модуля, а не импортировать весь модуль, вам понадобится и более поздняя функция, потому что от нее зависит throttlePeriod.
const fetchMaxThreePerSecond = throttlePeriod(3,1100)/*give it an extra 100*/(fetch)
Promise.all(
urls.map(fetchMaxThreePerSecond)
).then(
resulst=>...
);
Это заботится о дросселировании, но если вы знаете, как Promise.all
работает, вы знаете, что все обещания отклоняются, если только одно отклоняет. Так что, если у вас есть сто URL и 99 решимости, но один отклоняет ваш .then
никогда не звонят. Вы потеряете 99 успешных запросов.
Вы могли бы передать обещание 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));
}
)
}
}
);
У меня нет проблем с вызовами истории GDAX, когда я устанавливаю свой ограничитель скорости на 3 вызова API каждые 2,1 секунды.
У меня возникают некоторые проблемы, когда я устанавливаю свой ограничитель скорости на 3 вызова API каждые 1,8 секунды.
Я проверил эти значения с помощью автоматических тестов.
Важно: все мои звонки в GDAX используют один и тот же ограничитель скорости (!)
Чтобы сохранить, используйте код из ответа @HMR вместе с моими проверенными параметрами.