如何获取Promise.all与axios请求的进度?批量图片加载进度条问题
问题解答
Promise.all 是否适用于该场景?
完全适用。Promise.all 可以让多个请求并行发起,大幅缩短总加载时间,这正是你需要的。你遇到的进度条不更新问题,并非 Promise.all 的缺陷,而是代码写法有误导致进度更新逻辑没有正确触发。
问题出在哪里?
你的代码中,.then(this.warehouse[warehouse].progress++) 这一行存在关键错误:这里直接执行了 progress++ 表达式,而非将其作为回调函数传递给 then。这会导致所有请求的进度更新在请求发起时就立刻执行完毕,而非在每个请求完成后触发,最终自然看不到加载过程中的进度变化。
修正后的实现方式
方案1:修正回调逻辑,保留 Promise.all
调整 then 的回调写法,让每个请求完成后再更新进度,同时可以直接在单个请求的回调里给对应文章赋值图片,无需等到所有请求完成后统一处理:
async load(warehouse) { const warehouseData = this.warehouse[warehouse]; // 重置进度计数器 warehouseData.progress = 0; await Promise.all( warehouseData.articles.map((article) => axios .get(`https://my.api/articles/pictures/${article.number}`) .then((response) => { // 给当前文章直接赋值图片数据 article.picture = response.data; // 请求完成后递增进度 warehouseData.progress++; }) .catch((error) => { // 可选:处理请求失败场景,比如标记错误或跳过 console.error(`加载图片失败:${article.number}`, error); warehouseData.progress++; }) ) ); }
方案2:控制并发数(可选优化)
如果一次性发起250个请求可能触发API限流,或者给服务器造成过大压力,可以限制并发请求数量(比如一次最多10个),同时依然能实时更新进度:
async load(warehouse) { const warehouseData = this.warehouse[warehouse]; warehouseData.progress = 0; const articles = warehouseData.articles; const concurrencyLimit = 10; // 自定义并发上限 let currentIndex = 0; async function processNextArticle() { if (currentIndex >= articles.length) return; const article = articles[currentIndex]; currentIndex++; try { const response = await axios.get(`https://my.api/articles/pictures/${article.number}`); article.picture = response.data; } catch (error) { console.error(`加载图片失败:${article.number}`, error); } finally { warehouseData.progress++; await processNextArticle(); // 完成一个请求后,立刻发起下一个 } } // 初始化并发请求队列 const initialTasks = Array(concurrencyLimit).fill().map(processNextArticle); await Promise.all(initialTasks); }
说明
- 方案1保持最大并行度,适合API允许高并发的场景,进度会在每个请求完成时实时更新。
- 方案2通过控制并发数,避免请求过载,同时保证进度更新的实时性。
内容的提问来源于stack exchange,提问作者Bouni
相关产品推荐
相关产品推荐

