没有看到你的实现,我只能提供一个通用的答案。
假设您的下载函数接收一个 fileId 并返回一个承诺,该承诺会在所述文件完成下载时解析。对于这个 POC,我将用一个 Promise 来模拟它,该 Promise 将在 200 到 500 毫秒后解析为文件名。
function download(fileindex) {
return new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve(`file_${fileindex}`);
},200+300*Math.random());
});
}
您有 1000 个文件,并希望以 100 次迭代下载它们,每次迭代 10 个文件。
让我们封装一些东西。我将声明一个接收起始 ID 和大小的函数,并返回 [N...N+size] ids
function* range(bucket, size=10) {
let start = bucket*size,
end=start+size;
for (let i = start; i < end; i++) {
yield i;
}
}
您应该创建 100 个“桶”,每个“桶”包含对 10 个文件的引用。
let buckets = [...range(0,100)].map(bucket=>{
return [...range(bucket,10)];
});
此时,buckets的内容为:
[
[file0 ... file9]
...
[file 990 ... file 999]
]
然后,使用for..of(支持异步)遍历您的存储桶
在每次迭代中,使用 Promise.all 将 10 次调用排队到 download
async function proceed() {
for await(let bucket of buckets) { // for...of
await Promise.all(bucket.reduce((accum,fileindex)=>{
accum.push(download(fileindex));
return accum;
},[]));
}
}
让我们看一个正在运行的示例(只有 10 个存储桶,我们都在这里很忙 :D)
function download(fileindex) {
return new Promise((resolve, reject) => {
let file = `file_${fileindex}`;
setTimeout(() => {
resolve(file);
}, 200 + 300 * Math.random());
});
}
function* range(bucket, size = 10) {
let start = bucket * size,
end = start + size;
for (let i = start; i < end; i++) {
yield i;
}
}
let buckets = [...range(0, 10)].map(bucket => {
return [...range(bucket, 10)];
});
async function proceed() {
let bucketNumber = 0,
timeStart = performance.now();
for await (let bucket of buckets) {
let startingTime = Number((performance.now() - timeStart) / 1000).toFixed(1).substr(-5),
result = await Promise.all(bucket.reduce((accum, fileindex) => {
accum.push(download(fileindex));
return accum;
}, []));
console.log(
`${startingTime}s downloading bucket ${bucketNumber}`
);
await result;
let endingTime = Number((performance.now() - timeStart) / 1000).toFixed(1).substr(-5);
console.log(
`${endingTime}s bucket ${bucketNumber++} complete:`,
`[${result[0]} ... ${result.pop()}]`
);
}
}
document.querySelector('#proceed').addEventListener('click',proceed);
<button id="proceed" >Proceed</button>