关于并发加载图片时图片的顺序问题

关于并发加载图片时图片的顺序问题

老师,我发现本节课中我们使用并发方式加载图片时,得到的图片顺序有可能和url数组的顺序不同,比如这样:

https://img1.sycdn.imooc.com//climg/63ebc1ca0986933a30721046.jpg

而按照url数组的顺序应该是这样:

https://img1.sycdn.imooc.com//climg/63ebc1dd09aeec3730721046.jpg

请问我们应该如何在顾及效率的情况下(不要用继发)解决这个问题

正在回答 回答被采纳积分+1

登陆购买课程后可参与讨论,去登陆

1回答
好帮手慕慕子 2023-02-15 10:23:59

同学你好,可以考虑在加载图片的时候,让其并发加载图片,此时只是在后台加载图片,并不需要将其追加显示到页面。然后结合Promise.all方法,再将加载的图片追加到页面中。示例:

https://img1.sycdn.imooc.com//climg/63ec423b09c2f92916121094.jpg

祝学习愉快~

  • 老师好!我试着按这样修改了一下,的确是可以实现按数组顺序加载显示图片的效果,但是发现进度条一上来就显示100%,最后所有图片都显示出来的时候消失。想问下这是因为改写之后loadImgAsync(url)是异步函数,前面又没有await,所以系统不会等待他执行完毕再执行下面的代码,而是在其加载时就先去执行了下面的done++和progress.update(),从而导致done一上来就是3,所以进度条一上来就显示100%吗?


    想问下如果是这样的话,有没有什么好的办法可以解决这个问题呢?也就是让进度条能够随着图片加载进度而变化,而不是一上来就显示100%。


    期待老师解答,谢谢~

    2023-03-15 21:56:59
  • 同学你好, 问题解答如下:

    1、理解是对的

    2、可以考虑在图片加载成功事件中处理进度条解决这个小问题,参考下面的代码测试下

    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="UTF-8" />
    <title>页面加载进度条</title>
    <style>
    html,
    body,
    .progress {
    padding: 0;
    margin: 0;
    width: 100%;
    height: 100%;
    }
    img {
    max-width: 100%;
    }
    .progress {
    display: flex;
    justify-content: center;
    align-items: center;
    }
    .none {
    display: none;
    }
    </style>
    </head>
    <body>
    <div id="progress" class="progress">0%</div>
     
    <div id="content" class="none"></div>
     
    <script>
    function wait(ms) {
    return new Promise((resolve) => {
    setTimeout(resolve, ms);
    });
    }
    // 全局定义done方便计算
    let done = 0;
    // 多传参数
    // function loadImgAsync(url) {
    function loadImgAsync(url, $el, total) {
    return new Promise((resolve, reject) => {
    const $img = new Image();
     
    $img.addEventListener(
    "load",
    async () => {
    // await wait(1000);
    // 成功加载图片后将done值加一
    done++;
    // 计算进度条
    $el.innerHTML = `${parseInt((done / total) * 100)}%`;
    resolve($img);
    },
    false
    );
    $img.addEventListener(
    "error",
    () => {
    reject(new Error("Could not load image at " + url));
    },
    false
    );
     
    $img.src = url;
    });
    }
     
    class Progress {
    constructor($el) {
    this.$el = $el;
    }
     
    update(done, total) {
    this.$el.innerHTML = `${parseInt((done / total) * 100)}%`;
    }
     
    hide() {
    console.log("hide");
    this.$el.classList.add("none");
    }
    }
     
    (async () => {
    // const imgUrls = ['./ad.jpg', './ad_psyc.jpg', './logo.png'];
    const imgUrls = [
    "https://img1.mydrivers.com/Img/20100731/08213345.jpg",
    "https://img1.mydrivers.com/Img/20100731/08230220.jpg",
    "https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimg2.niutuku.com%2Fdesk%2F1208%2F2007%2Fntk-2007-25584.jpg&refer=http%3A%2F%2Fimg2.niutuku.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1654222356&t=c1a0d60776a99882cc8e22192c4b12c1",
    ];
    const total = imgUrls.length;
     
    const $content = document.getElementById("content");
    const $el = document.getElementById("progress");
    const progress = new Progress($el);
    // const progress = new Progress(document.getElementById("progress"));
     
    // 并发
    // 声明数组保存loadImgAsync方法调用返回的结果
    const promiseArr = [];
    // 将其加入数组中,此时的loadImgAsync(url)是异步执行,也就意味着在并发加载图片
    for (const url of imgUrls) {
    promiseArr.push(loadImgAsync(url, $el, total));
    }
    // 结合Promise.all处理
    const datas = await Promise.all(promiseArr);
    datas.forEach(($img) => {
    // 追加到页面
    $content.appendChild($img);
    });
    // await wait(1000);
    progress.hide();
    $content.classList.remove("none");
    })();
    </script>
    </body>
    </html>

    祝学习愉快~

    2023-03-16 18:21:05
  • 试了一下的确是可以解决进度条的问题了,感谢老师耐心解答!

    2023-03-16 23:07:08
问题已解决,确定采纳
还有疑问,暂不采纳

恭喜解决一个难题,获得1积分~

来为老师/同学的回答评分吧

0 星
请稍等 ...
意见反馈 帮助中心 APP下载
官方微信

在线咨询

领取优惠

免费试听

领取大纲

扫描二维码,添加
你的专属老师