例子:存在多个图片资源,已有加载函数loadImg,输入url返回一个promise;该promise在图片下载完成时resolve,下载失败则reject。要求并发下载,控制并发数量。
var urls = ["https://hexo-blog-1256114407.cos.ap-shenzhen-fsi.myqcloud.com/yi-painting1.png",
"https://hexo-blog-1256114407.cos.ap-shenzhen-fsi.myqcloud.com/yi-painting2.png",
"https://hexo-blog-1256114407.cos.ap-shenzhen-fsi.myqcloud.com/yi-painting3.png",
"https://hexo-blog-1256114407.cos.ap-shenzhen-fsi.myqcloud.com/yi-painting4.png",
"https://hexo-blog-1256114407.cos.ap-shenzhen-fsi.myqcloud.com/yi-painting5.png",
"https://hexo-blog-1256114407.cos.ap-shenzhen-fsi.myqcloud.com/bpmn6.png",
"https://hexo-blog-1256114407.cos.ap-shenzhen-fsi.myqcloud.com/bpmn7.png",
"https://hexo-blog-1256114407.cos.ap-shenzhen-fsi.myqcloud.com/bpmn8.png", ];
function loadImg(url)
{
return new Promise((resolve, reject) =>
{
const img = new Image();
img.onload = function() {
console.log("一张图片加载完成");
resolve(img);
};
img.onerror = function()
{
reject(new Error('Could not load image at' + url));
};
img.src = url;
});
解析:我们可以先请求url中的前limt个,并且请求时使用promise.race()同时请求。其中有一个完成就把当前请求数组中完成的一项,换成未执行请求的其他项。url遍历完成,最后剩下limt个没完成的请求则使用promise.all()来执行。
function limitLoad(urls, handler, limit)
{
let sequence = [].concat(urls); // 复制urls
let promises = sequence.splice(0,limit).map((url,index)=>{
//promises是一个执行栈,存储了发起请求的promise。splice()改变原数组。
return handler(url).then(()=>{
//通过promise.race控制获得最先执行完的index
return index
})
})
//sequence被截取了一部分作为执行栈,从urls[limit+1]开始迭代执行。
return sequence.reduce((pCollect,url)=>{
return pCollect.then(()=>{
return Promise.race(promises) //得结果index
}).then((index)=>{
promises[index] = handler(url).then(()=>index)
}).catch(err=>console.log(err))
},Promise.resolve())
.then(()=>{
return Promise.all(promises)
})
}
limitLoad(urls, loadImg, 5)
.then(res =>
{
console.log("图片全部加载完毕");
console.log(res);
}).catch(err =>
{ console.error(err); });