`window.location.href` 取消了对 API 的异步调用。

huangapple go评论56阅读模式
英文:

window.location.href cancels async calls to API

问题

以下是代码部分的翻译:

当代码运行时window.location.href 在所有异步调用到API完成之前就会触发如果我在位置上设置一个断点它就能正常工作

如何等待所有调用完成后再调用 window.location.href

代码

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");
    }
};
英文:

When the code runs window.location.href kicks in before all async calls to the API is done. If I set a breakpoint on the location it works fine.

How can wait until all calls are done before invoking window.location.href?

Code:

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");
}
};

答案1

得分: 2

你可以使用 Promise.all 来等待一组 Promise 完成。(Array#forEach 不适用于处理 Promise。)

在这里,我们可以使用 Array#map 来创建一个包含由 getLineNumbers() 返回的数组中每个元素的 Promise 的数组。

await Promise.all(getLineNumbers().map(async nr => {
	// 其他代码...
	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 });
}));
// 设置位置在这里
英文:

You can use Promise.all to wait for an array of Promises to be completed. (Array#forEach is not designed to work with Promises.)

Here, we can use Array#map to create an array containing a Promise for each element in the array returned by getLineNumbers().

await Promise.all(getLineNumbers().map(async nr => {
	// other code...
	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 });
}));
// set location here

答案2

得分: 0

每个单独的异步操作似乎在内部使用await,但没有等待所有这些操作。更确切地说,saveInvoice 是异步的,但它不会等待任何东西。

你可以用调用.map()来替代.forEach()来返回这些承诺:

const promises = getLineNumbers().map(async (nr) => {
  //...
});

然后等待这些承诺:

await Promise.all(promises);
window.location.href = "View/" + data.json.uId;
英文:

Each individual asynchronous operation appears to internally await, but nothing is awaiting all of those operations. More literally, saveInvoice is async but it doesn't await anything.

You can replace the call to .forEach() with a call to .map() to return the promises:

const promises = getLineNumbers().map(async (nr) => {
//...
});

Then await those promises:

await Promise.all(promises);
window.location.href = "View/" + data.json.uId;

huangapple
  • 本文由 发表于 2023年4月11日 03:38:47
  • 转载请务必保留本文链接:https://go.coder-hub.com/75980164.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定