两种方案网页进行图片预加载(限制并发)接口请求类似

接口请求只需要替换loadImage方法即可,逻辑类似

方式一有部分缺点

var urls = [
    'https://www.kkkk1000.com/images/getImgData/getImgDatadata.jpg',
    'https://www.kkkk1000.com/images/getImgData/gray.gif',
    'https://www.kkkk1000.com/images/getImgData/Particle.gif',
    'https://www.kkkk1000.com/images/getImgData/arithmetic.png',
    'https://www.kkkk1000.com/images/getImgData/arithmetic2.gif',
    'https://www.kkkk1000.com/images/getImgData/getImgDataError.jpg',
    'https://www.kkkk1000.com/images/getImgData/arithmetic.gif',
    'https://www.kkkk1000.com/images/wxQrCode2.png'
]
//每一张图片加载的函数,图片加载之后resolve
function loadImg(url) {
    return new Promise((resolve, reject) => {
        const img = new Image;
        img.onload = () => {
            console.log("加载完成", url);
            resolve()
        }
        img.src = url;
        img.onerror = reject
    })
}

/**
 * 预加载的主要逻辑
 * @param {Array} urls 表示需要加载的url的数组列表
 * @param {Number} limit 表示多少图片可以并发加载
 * @returns {Promise}
 */

function preLoad(urls, limit) {
    // 拷贝一份
    let urlsCopy = urls.slice(0);
    /**
     * 生成一个队列,首先队列的长度是前limit个url,因此使用slice进行切片,然后使用map函数返回一个加载完后的promise,
     * 这个promise返回当前url所在的队列中的位置的索引,以便后面加载完成url后将这个url进行替换。
     */
    let queue = urlsCopy.slice(0, limit).map((url, index) => loadImg(url).then(() => index).catch(() => index));

    /**
     * 这里将后面未加载的url切片出来,使用reduce函数在完成上一个加载之后再进行加载的url替换,可以传递默认值,
     * 因此可以使用Promise.resolve()作为默认值,在所有的队列中的promise都已解决后也就是Promise.allSettled(queue)
     * 完成后将这个promise返回出去作为preload函数的返回值就可以在.then()方法中操作
     * 缺点是队列中的前limit个若加载完成不能及时进行加载下一个
     */
    return urlsCopy.slice(limit).reduce((prev, currentUrl, currentIndex) => {
        return prev.then(() => {
            return Promise.race(queue).then(index => {
                // 将后面的图片进行替换
                return loadImg(currentUrl).then(() => {
                    queue[index] = currentIndex
                })
            })
        })
    }, Promise.resolve()).then(() => Promise.allSettled(queue))
}
preLoad(urls, 8).then(res => {
    console.log(res);
    console.log("全部加载完成");
})

更好的方式2

export function preloadImage(urls: string[], limit = 5) {
  const copyurls = [...urls];
  function loadImage(url: string) {
    return new Promise<string | HTMLImageElement>(resolve => {
      const image = lynx.createImage(url);
      image.addEventListener('load', () => {
        console.log(url, '加载成功');
        resolve(image);
      });
      image.addEventListener('error', () => {
        console.error(url, '加载失败');
        resolve(url);
      });
    });
  }
  /**
    * 生成一个队列,首先队列的长度是前limit个url,因此使用slice进行切片,然后使用map函数返回一个加载完后的promise
  	*/
  const taskQueue = copyurls.slice(0, limit).map((url, index) => loadImage(url).then(() => index));
  /**
    * 未加载url删除该长度
  	*/
  copyurls.splice(0, limit);
  /**
    * 使用递归进行入队操作
  	*/
  function enqueue(index: number): Promise<void> {
  /**
    * 如果未加载url列表为空就表示全部加载完成
  	*/
    if (copyurls.length === 0) {
      return Promise.resolve();
    }
    /**
    * 任务队列将已经加载完成的任务替换为当前的加载任务
  	*/
    taskQueue.splice(
      index,
      1,
      loadImage(copyurls.shift()!).then(() => index)
    );
    /**
    * 使用race方法,有任何一个加载完成时进行递归
  	*/
    return Promise.race(taskQueue).then(currentIndex => enqueue(currentIndex));
  }
  /**
    * 在最后将没有加载完的任务队列使用all方法进行加载
  	*/
  return Promise.race(taskQueue)
    .then(enqueue)
    .then(() => Promise.all(taskQueue));
}

const urls = [
  'https://www.kkkk1000.com/images/getImgData/getImgDatadata.jpg',
  'https://www.kkkk1000.com/images/getImgData/gray.gif',
  'https://www.kkkk1000.com/images/getImgData/Particle.gif',
  'https://www.kkkk1000.com/images/getImgData/arithmetic.png',
  'https://www.kkkk1000.com/images/getImgData/arithmetic2.gif',
  'https://www.kkkk1000.com/images/getImgData/getImgDataError.jpg',
  'https://www.kkkk1000.com/images/getImgData/arithmetic.gif',
  'https://www.kkkk1000.com/images/wxQrCode2.png',
];
preloadImage(urls).then(() => {
  console.error('全部加载成功');
});

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值