Promise.all()与setTimeout结合使用Throttle API调用

时间:2018-02-09 15:12:26

标签: javascript es6-promise

我有一组n个用户,我需要为每个用户点击API端点以获取更多信息,Promise.all()非常容易,但现在我的n已经变得更大了我现在需要将我的呼叫限制在每5秒50左右。有没有办法使用.reduce()setTimeout(() => {}, 5000)相结合,每5秒批量拨打50个电话,但仍然可以捕获Promise.all().then()中每个电话的结果?

// Retrieve data from an API endpoint for n users [works]
const users = [...array of 50 ids];

Promise.all(users.map(user => axios.get(`api/users/${user.id})))
       .then(results => resolve())
       .catch(err => reject(err));

2 个答案:

答案 0 :(得分:1)

你可以做这样的事情,这有点伪,但我相信你得到它的要点:):

const batchSize = 50;
const promises = [];
const users = [...lots of users];
const userCount =  users.length;
let userIdx=0;

function getUsers() { 
   for(let i=0;i<batchSize;i++) {
      if(userCount < ++userIdx) {
        Promise.all(promises).then(doYourStuff);
        return;
     }
     promises.push(axios.get('api/users/' + users[userIdx]));
   }       
   setTimeout(_ => getUsers(), 5000);
}

答案 1 :(得分:0)

谢谢!我对它进行了测试,然后对splicemap进行了清理,但它确实按预期工作。

const batchSize = 2;
const promises = [];
const users = ['a', 'b', 'c', 'd', 'e', 'f'];

function asyncTest(item) {
    return new Promise((resolve, reject) => {
        process.nextTick(() => {
            console.log(item);
            resolve(item);
        })
    })
}

function getUsers(xs) {
    if (!xs.length) {
        console.log("running 'em all");
        Promise.all(promises);
        return;
    }
    promises.push(xs.splice(0, batchSize).map(asyncTest));
    setTimeout(_ => getUsers(xs), 500);
}

getUsers(users);