如何等待所有异步API调用完成后再执行window.location.href跳转?
问题描述
当前代码执行时,window.location.href会在所有异步API调用完成前触发页面跳转;但在跳转代码处设置断点时,所有API调用能正常完成。需要修改代码实现等待所有异步API调用完成后再执行页面跳转。
原代码
const saveInvoice = async () => { if (containsItems()) { let customerId = document.getElementById("Customer").value; let date = document.getElementById("Date").value; let dueDate = document.getElementById("DueDate").value; let msgKID = document.getElementById("MSG").value; let accountId = document.getElementById("Account").value; let data = await WebRequest("InvoiceAPI", "CreateInvoiceAsync", null, { "CustomerId": customerId, "Date": date, "DueDate": dueDate, "MsgKID": msgKID, "AccountId": accountId }); getLineNumbers().forEach(async (nr) => { let prodId = parseInt(document.querySelector('select.prod[data-id=\"' + nr + '\"]').value); let descr = document.querySelector('input.description[data-id=\"' + nr + '\"]').value; let price = parseFloat(document.querySelector('span.price[data-id=\"' + nr + '\"] > span.sum').innerHTML); let mva = parseInt(document.querySelector('span.mva[data-id=\"' + nr + '\"] > span.sum').innerHTML); let mvaSum = parseFloat(document.querySelector('input.mva-value[data-id=\"' + nr + '\"]').value) let count = parseInt(document.querySelector('input.count[data-id=\"' + nr + '\"]').value); let perc = parseInt(document.querySelector('input.perc[data-id=\"' + nr + '\"]').value); let sum = parseFloat(document.querySelector('#Lines > div.line.row > div.amount-wrap[data-id=\"' + nr + '\"] span.line-sum').innerHTML); await WebRequest("InvoiceAPI", "CreateInvoiceLineAsync", null, { "InvoiceId": data.json.id, "ProductId": prodId, "Description": descr, "Count": count, "Discount": perc, "Price": price, "Mva": mva, "MvaSum": mvaSum, "Sum": sum }); }); window.location.href = "View/" + data.json.uId; } else { document.getElementById("InvoiceErrorWrap").classList.remove("hide"); } };
问题根源
forEach方法不会处理异步函数的返回值,也不会等待其中的await操作完成。循环执行时,每个异步调用会被触发,但代码会直接跳到window.location.href执行跳转,导致异步API还未完成就离开当前页面。
解决方案
将forEach替换为map生成Promise数组,再用Promise.all()等待所有异步操作完成后再执行跳转:
- 用
map遍历行号,每个迭代返回一个异步操作的Promise; - 使用
await Promise.all()等待所有Promise执行完毕; - 最后执行页面跳转。
修改后的代码
const saveInvoice = async () => { if (containsItems()) { let customerId = document.getElementById("Customer").value; let date = document.getElementById("Date").value; let dueDate = document.getElementById("DueDate").value; let msgKID = document.getElementById("MSG").value; let accountId = document.getElementById("Account").value; let data = await WebRequest("InvoiceAPI", "CreateInvoiceAsync", null, { "CustomerId": customerId, "Date": date, "DueDate": dueDate, "MsgKID": msgKID, "AccountId": accountId }); // 将forEach改为map生成Promise数组,并用Promise.all等待所有完成 const linePromises = getLineNumbers().map(async (nr) => { let prodId = parseInt(document.querySelector('select.prod[data-id=\"' + nr + '\"]').value); let descr = document.querySelector('input.description[data-id=\"' + nr + '\"]').value; let price = parseFloat(document.querySelector('span.price[data-id=\"' + nr + '\"] > span.sum').innerHTML); let mva = parseInt(document.querySelector('span.mva[data-id=\"' + nr + '\"] > span.sum').innerHTML); let mvaSum = parseFloat(document.querySelector('input.mva-value[data-id=\"' + nr + '\"]').value) let count = parseInt(document.querySelector('input.count[data-id=\"' + nr + '\"]').value); let perc = parseInt(document.querySelector('input.perc[data-id=\"' + nr + '\"]').value); let sum = parseFloat(document.querySelector('#Lines > div.line.row > div.amount-wrap[data-id=\"' + nr + '\"] span.line-sum').innerHTML); await WebRequest("InvoiceAPI", "CreateInvoiceLineAsync", null, { "InvoiceId": data.json.id, "ProductId": prodId, "Description": descr, "Count": count, "Discount": perc, "Price": price, "Mva": mva, "MvaSum": mvaSum, "Sum": sum }); }); // 等待所有发票行创建完成 await Promise.all(linePromises); // 所有异步操作完成后再跳转 window.location.href = "View/" + data.json.uId; } else { document.getElementById("InvoiceErrorWrap").classList.remove("hide"); } };
内容的提问来源于stack exchange,提问作者SteinTech
相关产品推荐
相关产品推荐

