You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何使用await的async图片加载函数拖慢了批量图片加载速度?

问题:批量图片加载的耗时差异疑问

我编写了如下图片加载函数:

export function loadImage(url: string): Promise<HTMLImageElement> {
    return new Promise((resolve, reject) => {
        if (image_map.has(url)) {
            resolve(image_map.get(url));
        } else {
            let image: HTMLImageElement = new Image();

            if (typeof window.static_url != 'undefined' && url[0] == '/') {
                image.src = `${window.static_url}${url}`;
            } else {
                image.src = url;
            }
            image_map.set(url, image);

            image.crossOrigin = 'Anonymous'; // Prevent canvas getImageData CORS issue
            image.onload = function () {
                resolve(image);
            };

            image.onerror = reject;
        }
    });
}

我需要加载约200张图片,此前使用如下代码加载:

for (let url of image_list) {
    await loadImage(url);
}

加载耗时极长,达到16秒甚至更久。

今天我移除了代码中的await,图片加载仅用了2秒完成。这是为什么?我以为JavaScript是单线程的,原本以为移除await只是让图片加载在其余代码之后执行,但总耗时不该有如此大的差异。


解答

核心原因是串行加载 vs 并行加载的区别,和JS单线程的特性并不冲突:

  • JS主线程确实是单线程,但浏览器的网络请求是由专门的网络线程处理的,JS只负责发起请求,之后等待回调通知结果。
  • 加await的循环是串行加载:每一次循环都会等待当前图片的loadImage Promise resolve(也就是图片加载完成),才会执行下一次循环、发起下一张图片的请求。200张图片就会排队依次加载,总耗时是所有图片加载时间的总和,自然会很长。
  • 移除await后是并行加载:循环会一次性遍历所有图片URL,调用loadImage时立刻创建Image实例、设置src,浏览器会同时发起多个网络请求(浏览器对同域名有并发数限制,一般是6-8个,剩下的会在已有请求完成后排队,但比起串行效率高太多)。总耗时基本由加载最慢的那几张图片决定,所以能从16秒大幅降到2秒。

你之前的误解在于:移除await不是让加载在其他代码之后执行,而是JS主线程不会等待每一张图片加载完成,而是一次性把所有请求都发出去,让浏览器并行处理这些网络请求,自然总耗时会大幅缩短。


内容的提问来源于stack exchange,提问作者Shaobin Jiang

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 05:00:32