Reputation: 113
I have a use case where I want to make an async call (consider it similar to ajax) and then in success block of that call I want to make a series of async calls in a loop using the id which is generated by parent call. My requirements are :
Sample code snippet :
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
});
Upvotes: 0
Views: 756
Reputation: 707158
Since it sounds like you want to run asyncCallB()
serially so you can avoid any additional calls if one of them fails, then this will be easiest to implement using async/await
.
To do this, you will have to mark the containing function as async
so you are allowed to use await
. You can then use await
to sequence your asynchronous operations:
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
}
}
For possibly faster performance, you can run your asyncCallB()
operations in parallel as shown below, but all asyncCallB()
calls will be run, even if the first one has an error (since they are all launched in parallel):
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
}
}
Upvotes: 1
Reputation: 364
The best option to ensure that the async chaining happens is to use an array.reduce function below is the sample code for the same.
if you are not clear about how array.reduce and promise work. I would suggest you refer to this article.
https://developers.google.com/web/fundamentals/primers/promises
Below is the sample code, which you can use.
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
});
Upvotes: 0
Reputation: 113
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
});
Upvotes: 0
Reputation: 951
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
});
Upvotes: 0