题目
顺序加载10张图片,图片地址已知,但是同时最多加载3张图片,要求用promise实现。
const baseUrl = 'http://img.aizhifou.cn/';
const urls = ['1.png', '2.png', '3.png', '4.png', '5.png','6.png', '7.png', '8.png', '9.png', '10.png'];
const loadImg = function (url, i) {
return new Promise((resolve, reject) => {
try {
// 加载一张图片
let image = new Image();
image.onload = function () {
resolve(i)
}
image.onerror = function () {
reject(i)
};
image.src = baseUrl + url;
} catch (e) {
reject(i)
}
})
}
function startLoadImage(urls, limits, endHandle) {
// 当前存在的promise队列
let promiseMap = {};
// 当前索引对应的加载状态,无论成功,失败都会标记为true,格式: {0: true, 1: true, 2: true...}
let loadIndexMap = {};
// 当前以及加载到的索引,方便找到下一个未加载的索引,为了节省性能,其实可以不要
let loadIndex = 0;
const loadAImage = function () {
// 所有的资源都进入了异步队列
if (Object.keys(loadIndexMap).length === urls.length) {
// 所有的资源都加载完毕,或者进入加载状态,递归结束
const promiseList = Object.keys(promiseMap).reduce((arr, item) => {arr.push(promiseMap[item]); return arr}, [])
Promise.all(promiseList).then(res => {
// 这里如果没有加载失败,就会在所有加载完毕后执行,如果其中某个错误了,这里的结果就不准确,不过这个不是题目要求的。
console.log('all');
endHandle && endHandle()
}).catch((e) => {
console.log('end:' + e);
})
} else {
// 遍历,知道里面有3个promise
while (Object.keys(promiseMap).length < limits) {
for (let i = loadIndex; i < urls.length; i++) {
if (loadIndexMap[i] === undefined) {
loadIndexMap[i] = false;
promiseMap[i] = loadImg(urls[i], i);
loadIndex = i;
break;
}
}
}
// 获取当前正在进行的promise列表,利用reduce从promiseMap里面获取
const promiseList = Object.keys(promiseMap).reduce((arr, item) => {arr.push(promiseMap[item]); return arr}, [])
Promise.race(promiseList).then((index) => {
// 其中一张加载成功,删除当前promise,让PromiseList小于limit,开始递归,加载下一张
console.log('end:' + index);
loadIndexMap[index] = true;
delete promiseMap[index];
loadAImage();
}).catch(e => {
// 加载失败也继续
console.log('end:' + e);
loadIndexMap[e] = true;
delete promiseMap[e];
loadAImage();
})
}
}
loadAImage()
}
startLoadImage(urls, 3)
帖子还没人回复快来抢沙发