我有一个拥有近2百万Facebook idSender的阵列,我想迭代它,为每一个调用一个Facebook API。 现在,由于异步性,如果我启动一个简单的for循环,Facebook会在4-5分钟后返回速率限制超过错误。 经过一些尝试后,我发现避免速率限制的理想延迟是20毫秒。
所以我尝试了这个解决方案:我将我的函数包装在Promise中,并使用setTimeout来设置延迟。
async function asyncLoop(values) {
var prm = await new Promise(function(resolve, reject) {
setTimeout(function() {
for (var i=0; i<values.length; i++) {
check(values[i].idSender, values[i].iscrizione, values[i].id_sito)
if(checked == values.length) {
resolve()
}
}
},20);
});
return prm;
}
asyncLoop(idSenderArray)
但是这个解决方案没有用,而且我也意识到使用setTimeout功能来操纵Javascript中的异步性几乎从来都不是一个好主意,事实上我甚至不能说出它到底发生了什么。
任何有关可能修改我的功能的建议?有关全新实施的任何想法都可行吗? 感谢
答案 0 :(得分:2)
在for循环中只需await
次:
const timer = ms => new Promise(res => setTimeout(res, ms));
async function asyncLoop(values) {
for (var i = 0; i < values.length; i++) {
await timer(20);
check(values[i].idSender, values[i].iscrizione, values[i].id_sito)
}
}
答案 1 :(得分:0)
你也可以用承诺来做这样的事情;
var apiCall = (url,n) => new Promise((v,x) => setTimeout(v,50,`the result of API call @ ${url} no ${n}`)),
calls = Array(20).fill()
.map((_,i) => new Promise((v,x) => setTimeout(v,20*i))
.then(_ => apiCall("http://facebook.com",i))
.then(v => console.log(`I am doing something with ${v}`)));
.as-console-wrapper{
height: 100%;
max-height: 100% !important
}
答案 2 :(得分:0)
或者,也可以使用带有promises的setTimeout:
async function asyncLoop(values) {
let apiCallPromises = values.map((value, index)=> new Promise(resolve=>{
setTimeout(_=>{
check(value.idSender, value.iscrizione, value.id_sito)
resolve()
}, index*20)
}))
return Promise.all(apiCallPromises);
}
相当直接的,它会将每个值映射到check()
调用,每个后续请求的延迟为20n ms。