[英]How to correctly handle a series of async calls inside a parent async call
我有一個用例,我想進行異步調用(認為它類似於 ajax),然后在該調用的成功塊中,我想使用父調用生成的 id 在循環中進行一系列異步調用。 我的要求是:
示例代碼片段:
asyncCallA(inputId)
.then(output => {
// inputIdsForChildCalls is the list of inputIds for child async
// calls
inputIdsForChildCalls = [do something with output]
for (let i = 0; i < inputIdsForChildCalls.length; i++) {
asyncCallB(inputIdsForChildCalls[i])
.then(output => {
// do something
})
.catch(error => {
// do something with error
});
}
showSuccessToast("Records created successfully!");
})
.catch(error => {
// do something with error
});
由於聽起來您想連續運行asyncCallB()
以便您可以在其中一個失敗時避免任何額外的調用,那么這將是使用async/await
最容易實現的。
為此,您必須將包含函數標記為async
以便您可以使用await
。 然后,您可以使用await
對異步操作進行排序:
async function someFunc(inputId) {
try {
let output = await asyncCallA(inputId);
// inputIdsForChildCalls is the list of inputIds for child async
// calls
let inputIdsForChildCalls = [do something with output]
for (let childId of inputIdsForChildCalls) {
let childResult = await asyncCallB(inputIdsForChildCalls[childId]);
// process child result here
// errors in asyncAllB() will have gone to the catch(e) statement below
}
showSuccessToast("Records created successfully!");
} catch(e) {
// handle error here
// throw an error here if you want the caller to be able to see the error
}
}
為了獲得更快的性能,您可以並行運行asyncCallB()
操作,如下所示,但所有asyncCallB()
調用都將運行,即使第一個調用有錯誤(因為它們都是並行啟動的):
async function someFunc() {
try {
let output = await asyncCallA(inputId);
// inputIdsForChildCalls is the list of inputIds for child async
// calls
let inputIdsForChildCalls = [do something with output]
let allResults = await Promise.all(inputIdsForChildCalls.map(childId => {
return asyncCallB(childId);
}));
// process allResults array here
// errors will have gone to the catch(e) statement below
showSuccessToast("Records created successfully!");
} catch(e) {
// handle error here
}
}
asyncCallA(inputId)
.then(output => {
inputIdsForChildCalls = [do something with output]
Promise.all(inputIdsForChildCalls)
.then(outputs => {
// do something
showSuccessToast("Records created successfully!");
})
.catch(error => {
// do something with error
});
}
})
.catch(error => {
// do something with error
});
asyncCallA(inputId)
.then(output => {
inputIdsForChildCalls = [do something with output]
let syncCalls = [];
for (let i = 0; i < inputIdsForChildCalls.length; i++) {
syncCalls.push(asyncCallB(inputIdsForChildCalls[i]));
}
Promise.all(inputIdsForChildCalls)
.then(outputs => {
// do something
showSuccessToast("Records created successfully!");
})
.catch(error => {
// do something with error
});
})
.catch(error => {
// do something with error
});
確保異步鏈接發生的最佳選擇是使用 array.reduce 函數,下面是相同的示例代碼。
如果您不清楚 array.reduce 和 promise 是如何工作的。 我建議你參考這篇文章。
https://developers.google.com/web/fundamentals/primers/promises
下面是示例代碼,您可以使用它。
asyncCallA(inputId)
.then(output => {
// inputIdsForChildCalls is the list of inputIds for child async
// calls
inputIdsForChildCalls = [];
inputIdsForChildCalls.reduce(function(sequence, Id)
{
return sequence.then(function()
{
return asyncCallB(Id);
}).then(function(asyncCallResult)
{
//do something
});
}, Promise.resolve())
})
.then(function()
{
showSuccessToast("Records created successfully!");
})
.catch(error => {
// do something with error
});
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.