校招刷题群
高效刷题 迎战校招
校招精选试题
近年面笔经面经群内分享
Java刷题群 前端刷题群 产品运营群
首页 > js语言和框架 > ES6相关(后面会废弃)
题目

顺序加载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)


解答

【解析】

将代码复制到chrome浏览器可以看到下面的运行结果:可以看到,所有图片加载完成,在没有失败的情况下,打印出来all。

解析:Promise.race方法接受的参数中有一个promise对象返回结果了就会立即触发成功或者失败的函数。这里利用这个特性,先将promise队列循环加入,直到达到限制,等待race,race后又加入一个promise,利用递归一直循环这个过程,到最后用promise.all捕获剩下的图片加载。

C 0条回复 评论

帖子还没人回复快来抢沙发