我从外部API获取数据,并且在某些端点上出现以下错误:
reason: getaddrinfo EAI_AGAIN [the url]:443
我只能假设API的所有者有某种速率限制器,并且因为所有提取都会立即被阻止。
所以我试图在每次获取之间加一个延迟,但没有运气。这是我的尝试:
class someClass {
...
dealyedFetch(url) {
return new Promise ((resolve, reject) => {
setTimeout(() => {
fetch(url, (err, res) => {
if (err) return reject(err)
return resolve(res)
})
}, 5000)
})
}
fetchUrls() {
return Promise.all(
this.urlList.map(url => {
return this.dealyedFetch(url)
.then(/* macht krieg */)
.catch(err => ({err, url}))
})
)
}
}
以上不起作用,它似乎立即触发所有取出。请照亮我。
答案 0 :(得分:2)
你立即将它们全部推迟,所以他们都等待5000毫秒,然后一起开火。
如果你想将它们串起来,你需要延长它们的延迟时间。您可以通过使用map
中的索引将多个延迟(例如500毫秒)加倍来实现:
delayedFetch(url, delay) { // ***
return new Promise ((resolve, reject) => {
setTimeout(() => {
fetch(url, (err, res) => {
if (err) return reject(err)
return resolve(res)
})
}, delay) // ***
})
}
fetchUrls() {
return Promise.all(
this.urlList.map((url, i) => { // ***
return this.delayedFetch(url, i * 500) // ***
.then(/* macht krieg */)
.catch(err => ({err, url}))
})
)
}
第一个请求根本没有延迟,第二个请求是1 * 500 = 500毫秒,第三个请求是2 * 500 = 1000毫秒等。
旁注:在上文中,我修改了名称delayedFetch
中的拼写错误(问题中dealyedFetch
,a
和l
被撤销了。)
附注2:上述内容解决了您实际问过的问题,但您可能会考虑一次只执行一次,在这种情况下this question's answers会告诉您如何执行此操作。或者可能是对优秀的并发限制,在这种情况下this question's answers会有所帮助。只是固定的延迟可能不是您的最佳解决方案。
答案 1 :(得分:0)
对于您的urlList
,您正在同时做出一系列承诺。这些承诺中的每一个等待5秒,然后它们全部同时执行(5秒后)。
有关在串行中运行promises的规范SO帖子,请参阅此内容: Resolve promises one after another (i.e. in sequence)?
从那篇帖子中解脱出来:
function runSerial(tasks) {
var result = Promise.resolve();
tasks.forEach(task => {
result = result.then(() => task());
});
return result;
}
然后你会通过用runSerial替换你的promise.all来消耗它。您可以通过一次释放5个url来进一步自定义逻辑,然后以串行方式运行批处理,但这应该可以帮助您开始。