封装一个批量加载图片的工具类

遇到一个面试题,把其中一部分功能单独封装了一个批量加载图片的class。

斗胆擅自加了一点功能,

1、 配置第一批同时发起load的图片数量(默认5张)。

2、无论成败,每结束一张图片加载自动加载下一张。

3、每张图片右侧实时展示目前加载状态(ready,pendding,success,failed)。

代码还在完善中,先上代码后续更新:

class ImgsLoader {
                constructor(srcs = [], BATCH_QUANTITY = 10) {
                    this.TOTAL_QUANTITY = srcs.length;
                    this.BATCH_QUANTITY = BATCH_QUANTITY;
                    this.IMG_INFOS = srcs.map((src, index) => {
                        this.PROGRESS = 0;
                        const dom = document.createElement('div');
                        dom.id = `innerItem-${index}`;
                        const progressText = document.createElement('span');
                        progressText.id = `innerItemText-${index}`;
                        progressText.innerText = "等待加载中...";
                        const img = new Image();
                        dom.appendChild(img);
                        dom.appendChild(progressText);
                        const imgInfo = {
                            src,
                            index,
                            status: 0, // 0: ready,1: pendding,2:success,3:failed
                            progress: 0,
                            progressText,
                            dom,
                            img
                        }
                        return imgInfo;
                    });
                }
                mount(selector) {
                    this.SELECTOR = selector;
                    if (!this.SELECTOR){
                        return;
                    }
                    this.IMG_INFOS.forEach(({dom}) => document.querySelector(this.SELECTOR)?.appendChild?.(dom));
                    this.IMG_INFOS.slice(0, this.BATCH_QUANTITY)?.forEach?.(imgInfo => {
                        this.load(imgInfo);
                    });
                }
                TOTAL_QUANTITY = 0;
                IMG_INFOS = [];
                SUCCESS_LIST = [];
                FAILED_LIST = [];
                BATCH_QUANTITY = 10;
                CURRENT_INDEX = 0;
                PROGRESS = 0;
                SELECTOR = null;
                async load(imgInfo) {
                    return new Promise((resolve, reject) => {
                        const img = imgInfo.img;
                        imgInfo.status = 1;
                        img.onload = () => {
                            img.onload = null;
                            imgInfo.status = 2; // 0: ready,1: pendding,2:success,3:failed
                        }
                        img.onerror = () => {
                            img.onerror = null;
                            img.onabort = null;
                            imgInfo.status = 3; // 0: ready,1: pendding,2:success,3:failed
                        }
                        img.onabort = img.onerror
                        img.src = imgInfo.src;
                        this.recursiveCheckStatus(imgInfo, resolve, reject);
                    });
                }
                recursiveCheckStatus(imgInfo, resolve, reject) {
                    requestAnimationFrame(() => {
                        // 0: ready,1: pendding,2:success,3:failed
                        if (imgInfo.status === 1) {
                            imgInfo.progress = imgInfo.progress < 100 ? (imgInfo.progress + 1) : imgInfo.progress;
                            imgInfo.progressText.innerText = `加载进度${imgInfo.progress}%`
                            setTimeout(this.recursiveCheckStatus.bind(this, imgInfo, resolve, reject), 500);
                            return;
                        }
                        if (imgInfo.status === 2) {
                            imgInfo.progressText.innerText = "加载成功"
                            if ((this.CURRENT_INDEX + 1) < this.TOTAL_QUANTITY) {
                                this.CURRENT_INDEX++;
                                const nextInfo = this.IMG_INFOS.find(({index}) => index === this.CURRENT_INDEX);
                                nextInfo && this.load(nextInfo);
                            }
                            this.PROGRESS = this.CURRENT_INDEX + 1;
                            resolve?.();
                            return;
                        }
                        if (imgInfo.status === 3) {
                            imgInfo.progressText.innerText = "加载失败"
                            if ((this.CURRENT_INDEX + 1) < this.TOTAL_QUANTITY) {
                                this.CURRENT_INDEX++;
                                const nextInfo = this.IMG_INFOS.find(({index}) => index === this.CURRENT_INDEX);
                                nextInfo && this.load(nextInfo);
                            }
                            this.PROGRESS = this.CURRENT_INDEX + 1;
                            reject?.();
                        }
                    })
                }
            }
            
         
            // 使用:
            const loader = new ImgsLoader(['https://img1.baidu.com/it/u=754329322,2526521035&fm=253&fmt=auto&app=138&f=JPEG?w=889&h=500', 'https://img0.baidu.com/it/u=3749906677,2827831142&…p;fmt=auto&amp;app=120&amp;f=JPEG?w=800&amp;h=500', 'https://img2.baidu.com/it/u=3200016476,4256473359&fm=253&fmt=auto&app=138&f=PNG?w=360&h=200'], 2)
            loader.mount("#list");

 

posted @ 2024-08-10 23:41  筑潇  阅读(29)  评论(0)    收藏  举报