如何正确处理父异步调用中的一系列异步调用



我有一个用例,我想进行一个异步调用(考虑它类似于ajax(,然后在该调用的成功块中,我想使用父调用生成的id在循环中进行一系列异步调用。我的要求是:

  1. 显示成功吐司的代码放在哪里?目前,我将它放在成功块中的for循环之后,但它有一个问题,即它将在子异步调用完成之前执行,因为for循环不会等待调用,很快就会执行,代码将显示成功吐司
  2. 如果任何一个子调用失败,那么就不应该再进行调用了(这更多地是从效率的角度来看的(,而且在这种情况下,我应该能够删除创建的父记录,那么如何处理呢?提前感谢

示例代码片段:

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

最新更新