如何调整代码使console.log(url)在each循环全部执行完成后调用
问题核心原因
jQuery的each方法不支持等待异步回调执行完成,你传入的async函数执行到await就会返回pending状态的Promise,each不会感知这些Promise的状态,遍历完就直接执行后面的代码,所以才会出现console.log(url)先打印的情况。
解决方法
把所有异步操作封装成Promise数组,用Promise.all等待全部执行完成后再执行后续逻辑,修改后的代码如下:
$("form").on('submit', async (e) => { e.preventDefault(); const form = $("form"); if (!form.checkValidity()) return; const formData = new FormData(form[0]); // 把jQuery对象转成数组,map返回所有异步操作的Promise const uploadPromises = $(".file-upload-wrapper img.card-img").map(async function (i) { const src = $(this).attr("src"); const fileName = $(this).attr("data-filename"); const response = await fetch(src); const data = await response.blob(); formData.append("file", data, fileName); console.log(src); }).get(); // 把jQuery map返回的对象转成普通数组 // 等待所有异步操作完成 await Promise.all(uploadPromises); const url = $(form).attr("action"); console.log(url); })
补充说明
- 首先给submit的事件回调加上
async关键字,这样回调内部才可以使用await语法 - 用
map方法遍历所有img元素,每个元素的异步处理逻辑会返回一个Promise,最终得到一个Promise数组 - 调用
await Promise.all(uploadPromises),代码会阻塞在这里直到所有Promise都执行完成,之后才会执行后面的url打印逻辑 - 如果需要实现单个请求失败不影响其他请求的逻辑,可以把
Promise.all换成Promise.allSettled,自行判断每个请求的执行状态
内容的提问来源于stack exchange,提问作者Mikhail
相关产品推荐
相关产品推荐

