user1608841
user1608841

Reputation: 2475

Calling Sequencial HTTP request 100 times

Here's the problem statement:

I came up with following rxjs implementation using nested concatMap:

import { range } from 'rxjs/observable/range';
import { concatMap } from 'rxjs/operators';
import { tap } from 'rxjs/operators/tap';

@Component({
  selector: 'app-flow',
  templateUrl: './flow.component.html',
  styleUrls: ['./flow.component.scss']
})
export class FlowComponent implements OnInit {

  constructor(public dataCallService: DataCallService) { }
  ngOnInit() {
    range(1, 100).pipe(
      tap((d) => console.log(d)),
      concatMap(() => this.dataCallService.firstAPI(data1).pipe(
        concatMap(() => this.dataCallService.secondAPI(data2))
      ))
    ).subscribe(res => {
      console.log(res)
    });
  }
 }

Although this works fine; tap operator I used emits 1 to 100 immediatly. I am not sure whether its correct approach. Is there any better approach to achieve the same ?

Upvotes: 2

Views: 512

Answers (1)

Estus Flask
Estus Flask

Reputation: 222760

In order for the requests to be chained, it should be something like:

Observable.range(1, 100).map(i =>
  this.dataCallService.firstAPI(data1)
  .concatMap(() => this.dataCallService.secondAPI(data2))
})
.concatAll()
.subscribe(res => {});

Request observables can be conveniently handled with promises in Angular, because both Http and HttpClient result in complete observable with single value.

Unless request observable is supposed to be aborted in the middle of a request or piped with other incomplete/multi-value observables, it may be beneficial to switch to promises.

This results in very straightforward async function where Promise.all is used for requests that can be performed in parallel:

  async ngOnInit() {
    try {
      for (let i = 0; i < 100; i++) {
        const [result1, result2] = await Promise.all([
          this.dataCallService.firstAPI(data1).toPromise(),
          this.dataCallService.secondAPI(data2).toPromise()
        ]);
      }
    } catch (err) { ... }
  }

Or in series:

  async ngOnInit() {
    try {
      for (let i = 0; i < 100; i++) {
        const result1 = await this.dataCallService.firstAPI(data1).toPromise();
        const result2 = await this.dataCallService.secondAPI(data2).toPromise();
      }
    } catch (err) { ... }
  }

Upvotes: 2

Related Questions