- Published on
分批加载图片列表——队列的使用
- Authors
- Name
- piczi
现在有个需求:从服务端获取到一个图片列表,为了增强用户体验,需要从前往后每3张分批加载图片,我们可以用队列的理念解决这个问题。什么是队列呢?维基百科对它的解释:
队列,又称为伫列(queue),计算机科学中的一种抽象资料类型,是先进先出(FIFO, First-In-First-Out)的线性表。在具体应用中通常用链表或者数组来实现。队列只允许在后端(称为rear)进行插入操作,在前端(称为front)进行删除操作。
我们可以把它理解成一个先进先出的数组,即首先把图片列表的1到3的图片放进数组,这3张图片加载完成后就把他们推出队列,然后把4到6的图片放进队列并加载,重复以上操作,直至在在玩所有图片。下面是实现代码:
const fetchImgList = () => {
return new Promise((resolve) => {
setTimeout(() => {
resolve([
'https://cn.bing.com/th?id=OHR.GimignanoTuscany_ZH-CN8059318824_1920x1080.jpg&rf=LaDigue_1920x1080.jpg&pid=hp',
'https://cn.bing.com/th?id=OHR.CorbettTigers_ZH-CN6927569938_1920x1080.jpg&rf=LaDigue_1920x1080.jpg&pid=hp',
'https://cn.bing.com/th?id=OHR.BeachHutsSweden_ZH-CN4193150313_1920x1080.jpg&rf=LaDigue_1920x1080.jpg&pid=hp',
'https://cn.bing.com/th?id=OHR.RhinelandVineyards_ZH-CN3332101688_1920x1080.jpg&rf=LaDigue_1920x1080.jpg&pid=hp',
'https://cn.bing.com/th?id=OHR.PontNeuf_ZH-CN3158359446_1920x1080.jpg&rf=LaDigue_1920x1080.jpg&pid=hp',
'https://cn.bing.com/th?id=OHR.SmokyMountainTrail_ZH-CN4691667074_1920x1080.jpg&rf=LaDigue_1920x1080.jpg&pid=hp',
'https://cn.bing.com/th?id=OHR.SheepCousins_ZH-CN4262132476_1920x1080.jpg&rf=LaDigue_1920x1080.jpg&pid=hp',
'https://cn.bing.com/th?id=OHR.MethoniCastle_ZH-CN4054146065_1920x1080.jpg&rf=LaDigue_1920x1080.jpg&pid=hp',
]);
}, 500);
});
};
// 首先请求接口拿到图片列表,然后分批放入队列请求图片
const list = await fetchImgList();
const queue = [];
for (let i = 0; i < list.length; i += 3) {
queue.push(list.slice(i, i + 3)?.filter(item => !!item));
}
console.log(queue);
然后请求队列中的图片,请求完成后把图片链接推出队列,并把图片显示在页面上。
while (queue.length) do {
try {
// 加载队列中的图片,加载后把图片推出队列
} catch (e) {
}
}
完整代码如下:
const fetchImgList = () => {
return new Promise((resolve) => {
setTimeout(() => {
resolve([
'https://cn.bing.com/th?id=OHR.GimignanoTuscany_ZH-CN8059318824_1920x1080.jpg&rf=LaDigue_1920x1080.jpg&pid=hp',
'https://cn.bing.com/th?id=OHR.CorbettTigers_ZH-CN6927569938_1920x1080.jpg&rf=LaDigue_1920x1080.jpg&pid=hp',
'https://cn.bing.com/th?id=OHR.BeachHutsSweden_ZH-CN4193150313_1920x1080.jpg&rf=LaDigue_1920x1080.jpg&pid=hp',
'https://cn.bing.com/th?id=OHR.RhinelandVineyards_ZH-CN3332101688_1920x1080.jpg&rf=LaDigue_1920x1080.jpg&pid=hp',
'https://cn.bing.com/th?id=OHR.PontNeuf_ZH-CN3158359446_1920x1080.jpg&rf=LaDigue_1920x1080.jpg&pid=hp',
'https://cn.bing.com/th?id=OHR.SmokyMountainTrail_ZH-CN4691667074_1920x1080.jpg&rf=LaDigue_1920x1080.jpg&pid=hp',
'https://cn.bing.com/th?id=OHR.SheepCousins_ZH-CN4262132476_1920x1080.jpg&rf=LaDigue_1920x1080.jpg&pid=hp',
'https://cn.bing.com/th?id=OHR.MethoniCastle_ZH-CN4054146065_1920x1080.jpg&rf=LaDigue_1920x1080.jpg&pid=hp',
]);
}, 500);
});
};
const imgList = await fetchImgList();
const batchLoadImages = async (list, batchCount = 3) => {
const loadImg = (imgSrc) => {
return new Promise((resolve, reject) => {
const img = new Image();
img.src = imgSrc;
img.onload = () => {
document.body.appendChild(img);
resolve();
}
img.onerror = (e) => {
reject(e.message);
}
})
};
const queue = [];
// 分批放入队列
for (let i = 0; i < list.length; i += batchCount) {
queue.unshift(list.slice(i, i + batchCount)?.filter(item => !!item));
}
while (queue.length) {
const requester = queue[queue.length - 1].map(item => loadImg(item));
await Promise.all(requester);
queue.pop();
}
};
batchLoadImages(imgList);