简体   繁体   English

优化 api 调用 rxjs

[英]optimise api calls rxjs

I have an array , and i want to loop through the array and call server data on each item .我有一个数组,我想遍历数组并调用每个项目的服务器数据。 I want to show a spinner as api is being in pending state as i load the page.我想在加载页面时显示一个微调器,因为 api 处于挂起状态。

Current solution:当前解决方案:

  getRecordings(classroom) {
    return this.sysAdminService.getMeetingRecordings(classroom.meeting_id).subscribe(res => {
      classroom.recordings = res;
    });
  }

Api calls: Api 调用:

 this.classRoomsToDisplay.map((classroom) => {
      classroom.showAttendees = false;
      classroom.recordings = null;
      this.getRecordings(classroom);
    });

As above im subscribing to the observable for each item in an array .I want to find if there is any better way to do this using rxjs , concatMap?如上所述,我订阅了数组中每个项目的 observable。我想知道是否有更好的方法使用 rxjs、concatMap 来做到这一点? i dont want to wait for the api calls for the entire array to be completed , i want to display the result as soon as the api call for that item is completed.我不想等待整个数组的 api 调用完成,我想在该项目的 api 调用完成后立即显示结果。

From the data you've shown, it isn't clear which property you're using to display the data.从您显示的数据中,不清楚您使用哪个属性来显示数据。 I'll assume it's classroom.showAttendees since it's a boolean.我假设它是classroom.showAttendees因为它是一个布尔值。

You could use RxJS forkJoin function to combine multiple observables and subscribe once instead of having multiple subscriptions.您可以使用 RxJS forkJoin函数来组合多个 observable 并订阅一次,而不是有多个订阅。 And you could toggle the showAttendees flag for each item in the array as a side-effect using tap operator.您可以使用tap运算符切换数组中每个项目的showAttendees标志作为副作用。

Try the following尝试以下

complete$ = new Subject<any>();

getRecordings(classroom): Observable<any> {   // <-- return the HTTP request observable
  return this.sysAdminService.getMeetingRecordings(classroom.meeting_id).pipe(
    tap => {
      classroom.showAttendees = true;         // <-- set the flag to show data
      classroom.recordings = res;
    }
  );
}

ngOnInit() {
  // `reqs` is an array of observables `[getRecordings(classroom), getRecordings(classroom), ...]`
  const reqs = this.classRoomsToDisplay.map((classroom) => {
    classroom.showAttendees = false;
    classroom.recordings = null;
    return this.getRecordings(classroom);
  });

  forkJoin(reqs).pipe(takeUntil(this.complete$)).subscribe();   // <-- trigger the HTTP requests
}

ngOnDestroy() {
  this.complete$.next();        // <-- close open subscriptions
}

Template模板

<div *ngFor="classroom of classRoomsToDisplay">
  <ng-container *ngIf="classroom.showAttendees">
    {{ classroom.recordings }}
  </ng-container>
</div>

Now since we're assigning the values in the tap operator, data for each item will be shown as soon as they arrive.现在,由于我们在tap运算符中分配值,因此每个项目的数据将在它们到达时立即显示。

You should prefer using the async pipe instead of the subscription.您应该更喜欢使用异步管道而不是订阅。

Example:例子:

<ul>
  <li *ngFor="let attendee of attendeesWithData">Attendee: {{ attendee.attendee }}, duplicated: {{ (attendee.duplication | async) || 'pending' }}</li>
</ul>

In this example the async operation is a duplication of the string and the request takes longer each time for demonstration.在这个例子中,异步操作是字符串的重复,每次请求需要更长的时间来演示。

@Injectable()
export class DuplicateService {

  times = 1;

  constructor() { }

  getDuplicated(s: string): Observable<string> {
    return timer(1000 * this.times++).pipe(
      map(() => s + s),
    );
  }
}
@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {
  private attendees: string[] = ['A', 'B', 'C', 'D', 'E', 'F'];

  attendeesWithData = this.attendees.map(attendee => ({ 
    attendee,
    duplication: this.duplicateService.getDuplicated(attendee),
  }));

  constructor(private duplicateService: DuplicateService) {}
}

As a result each second one list item switches its state from pending to the duplicated string.结果,每一秒一个列表项都将其状态从挂起切换到重复的字符串。

See also the stackblitz: https://stackblitz.com/edit/angular-ivy-rtx6cg?file=src/app/app.component.ts另见stackblitz: https ://stackblitz.com/edit/angular-ivy-rtx6cg ? file = src/app/app.component.ts

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM