I have the following for loop which works correctly in my code. However it needs to do multiple api calls as it loops through, which is taking a long time, so i am trying to figure out whether i could do a promise all and run the api calls all at once.
But really not sure how to go about it, with how my code works, so hoping someone might be able to help.
Below is my code:
let terms = []
this.selectedGroup.groups = ['A', 'B', 'C', 'D', 'E', 'F']
//loop through each term
for (let term of this.terms) {
let subjects: any = [];
//loop through each terms assessments
for (let assessment of term.assessments) {
//loop through the assessment year groups
for (let assessmentGroup of assessment.year_groups) {
//only get the assessments for the particular year group we are looking at
if (this.selectedGroup.groups.includes(assessmentGroup.name)) {
//get the subject data for this assessment
let newSubjects = await this.dataService.getData(
assessment,
assessmentGroup,
this.selectedGroup.students
);
//add the assessment subjects to the overall subjects array
subjects = subjects.concat(newSubjects)
}
}
}
//push all the subjects for the term into a terms array
terms.push({
name: term._id,
subjects: subjects,
});
}
Is there anyway of introducing a promise all to this, so the api calls can run at once? Thanks in advance!
CodePudding user response:
Here are the steps to take:
Remove the
await
keyword where you currently have it. So nowsubjects
will be an array of promises.Add
await Promise.all
in yourpush
call:terms.push({ name: term._id, subjects: (await Promise.all(subjects)).flat(), });
That's it: now there will multiple pending promises until one item is pushed to the terms
array. This should already give some improvement.
If you want to have even more simultaneous pending promises, then also make terms
an array of promises:
terms.push(Promise.all(subjects).then(subjects => ({
name: term._id,
subjects: subjects.flat(),
})));
And then, after the outermost loop, have a one-for-all await:
terms = await Promise.all(terms);
CodePudding user response:
You can put the this.dataService.getData call in a array and in the of the assessment.year_groups loop resolve all promises with Promises.all method.
let terms = []
let promises = [];
this.selectedGroup.groups = ['A', 'B', 'C', 'D', 'E', 'F']
//loop through each term
for (let term of this.terms) {
let subjects: any = [];
//loop through each terms assessments
for (let assessment of term.assessments) {
//loop through the assessment year groups
for (let assessmentGroup of assessment.year_groups) {
//only get the assessments for the particular year group we are looking at
if (this.selectedGroup.groups.includes(assessmentGroup.name)) {
//get the subject data for this assessment
promises.push(this.dataService.getData(
assessment,
assessmentGroup,
this.selectedGroup.students
));
}
}
Promise.all(promises).then(v => subjetcs.concat(v)) # resolve the promise here
}
//push all the subjects for the term into a terms array
terms.push({
name: term._id,
subjects: subjects,
});