angularsubscribe

CombineLatest and unknown number of API calls


I try to fetch data from multiple API calls on ngOnInit. First I need to check the number of calls and then I need to merge it all together in one array.

I was trying different approach and can't get my head around this. I think I should use combineLatest or some other operators but not sure which one. This for loop looks strange, but what's the other way to do it?

Here is sample code. Can someone help me fix it or give some hints?

    @Input() collection: string;
    userCodes: string[] = [];
    @Select(UsersState.userHash) userHash$!: Observable<userHash>;
    userHash= '';

    constructor(private dataService: DataService) {}

    ngOnInit(): void {
        this.getData();
    }

  getData() {
        this.userHash$
            .pipe(
                switchMap((userHash) => {
                    if (userHash) {
                        this.userHash = userHash;
                        if (this.collection) {
                            return this.dataService.getNumberOfCalls(userHash, this.collection);
                }),
                switchMap(numberOfCalls => {
                    for (let i = 0; i <= numberOfCalls ; i++) {
                    return this.dataService.getUserCodes(this.userHash, collection, i));
                }
               })
            )
            .subscribe((userCodes) => {
                        this.userCodes.push(...userCodes);
                    }
            });
    }

    getNumberOfCalls(collection: string) {
        this.dataService.getNumberOfCalls(this.userHash, collection).subscribe((res) => {
            if (Array.isArray(res)) {
                return 0;
            }

            return (Math.ceil(res?.size / 200);
    }

Solution

  • I would suggest to modify the second switchMap as follows:

    1. Create an array of http-request observables
    2. Use forkJoin to execute all observables in the array
    switchMap(numberOfCalls => {
        const apiCalls = [...Array(numberOfCalls).keys()].map(n => this.dataService.getUserCodes(this.userHash, collection, n));
        return apiCalls.length ? forkJoin(apiCalls) : of([]);
    })
    .subscribe(...