I am struggling with arrays in Angular.
This is the response I get from another function and I need to use
[
{
id: 1
name: Jane
age: 22
},
{
id: 2
name: Joe
age: 24
},
{
id: 3
name: Anna
age: 27
},
]
This response is stored in a variable
users: IUser[]=[]
I need to access every id from the user's array and pass it into another function.
I tried this:
list: IList[] = []
this.users.map(users => {
this.service
.someRandomFunctionINeed$(users.id)
.subscribe(data => {
if (data.length > 0) {
this.list = data
}
console.log('inside', this.list)
})
})
console.log('outside', this.list)
The problem is that the new list array is filled inside subscribe but outside of it is empty.
What am I doing wrong?
CodePudding user response:
If you need to perform an async function call for each user, and then access it after finishing all iterations, I would do the following:
async yourFunction() {
for (let user of this.users) {
console.log(user);
let observableData$ = this.service.someRandomFunctionINeed$(user.id);
// make the code wait until the call finishes, to be able to access it in the next line
const data: any = await firstValueFrom(observableData$);
console.log('your data loaded here', data);
if (data.length > 0) {
this.list = data;
}
console.log('inside', this.list);
}
console.log('you can read the data from this line on', this.list);
}
I changed the .map to a for loop (as you were not mapping the result of each iteration to anything), and made use of RxJS - firstValueFrom to transform the observable returned from your call into a Promise that I can await inside an async function.
CodePudding user response:
Is this what you want
use
from
from , Turn an array, promise, or iterable into an observablemergeMap
mergeMap, map id to API and emit values.
const { from, mergeMap, toArray, mergeAll, tap, of, delay } = rxjs;
const users = [1, 2, 3];
const api = (id) => { // this.service.someRandomFunctionINeed$(users.id)
const time = (Math.random() .5) * 1000;
console.log(`api ${id}, ${time} ms`)
return of([`user ${id}`]).pipe(delay(time));
};
const list1 = [];
from(users).pipe(
tap((id) => console.log('before mergeMap', id)),
mergeMap((id) => api(id)),
tap((data) => console.log('after mergeMap', data))
).subscribe({
next: (data) => list1.push(...data),
complete: () => console.log('complete', list1)
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/7.5.6/rxjs.umd.min.js"></script>
forkJoin
const { from, mergeMap, toArray, mergeAll, tap, of, delay, forkJoin } = rxjs;
const users = [1, 2, 3];
const api = (id) => { // this.service.someRandomFunctionINeed$(users.id)
const time = (Math.random() .5) * 1000;
console.log(`api ${id}, ${time} ms`)
return of([`user ${id}`]).pipe(delay(time));
};
const list2 = [];
forkJoin(users.map((id) => api(id).pipe(mergeAll()))).subscribe({
next: (data) => list2.push(...data),
complete: () => console.log('complete list2', list2)
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/7.5.6/rxjs.umd.min.js"></script>