当Rxjs 6中有一个新的请求时,如何取消正在进行的HTTP请求?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (1307)

我在下面代码中使用了RxnsSearchServiceRxnsSearchHitCountService,我的应用程序中有两个HTTP服务。

forkJoin处理两个请求,代码:

constructor(
  private rxnsSearchService: RxnsSearchService,
  private rxnsSearchHitCountService: RxnsSearchHitCountService
) { }
const rxnsObservable: Observable<Array<any>> = this.rxnsSearchService.getReactions(this.searchParams, filters);
const headCountObservable: Observable<number> = this.rxnsSearchHitCountService.getHitCount(this.searchParams, filters);
forkJoin([rxnsObservable, headCountObservable]).pipe().subscribe((results) => { //handling results 
},
  error => {
    console.log(error);
  });

每当有新的请求出现时,我想取消正在进行的旧请求。有人能帮我吗?

export class RxnsSearchService {
  sub: Subject<any> = new Subject();
  constructor(private httpClient: HttpClient) {}

  getReactions(params: Params, offset: number, perPage: number, filters: any) {
    const body = {
      filters: filters,
      query: params.query
    };
     return this.httpClient.post(environment.rxnsSearch, body).pipe(
      map((response: Array<any>) => {
        return response;
      }),
      catchError(error => {
        console.log(error);
        return throwError(error);
      })
    );
  }
}

export class RxnsSearchHitCountService {
  constructor(private httpClient: HttpClient) {}

  getHitCount(params: Params, filters: any) {
    const body = {
      filters: filters,
      query: params.query,
    };
    return this.httpClient.post(environment.rxnsSearchHitCount, body).pipe(
      map((response: number) => {
        return response;
      }),
      catchError(error => {
        console.log(error);
        return throwError(error);
      })
    );
  }
}

提问于
用户回答回答于

我将通过一个简化的例子来介绍如何实现它的一般方法。假设我们目前有:

public getReactions() {
  this.http.get(…)
    .subscribe(reactions => this.reactions = reactions);
}

确保取消旧请求的方法是在某些主题上发出邮件:

private reactionsTrigger$ = new Subject<void>();

public getReactions() {
  this.reactionsTrigger$.next();
}

现在,我们有了一个可观察的表示触发新请求的事件流。你现在可以用OnInit实现:

public ngOnInit() {
  this.reactionsTrigger$.pipe(
    // Use this line if you want to load reactions once initially
    // Otherwise, just remove it
    startWith(undefined),

    // We switchMap the trigger stream to the request
    // Due to how switchMap works, if a previous request is still
    // running, it will be cancelled.
    switchMap(() => this.http.get(…)),

    // We have to remember to ensure that we'll unsubscribe from
    // this when the component is destroyed
    takeUntil(this.destroy$),
  ).subscribe(reactions => this.reactions = reactions);
}

// Just in case you're unfamiliar with it, this is how you create
// an observable for when the component is destroyed. This helps
// us to unsubscribe properly in the code above
private destroy$ = new Subject<void>();
public ngOnDestroy() {
  this.destroy$.next();
  this.destroy$.complete();
}

这行:

    switchMap(() => this.http.get(…)),

在你的情况下,可能要切换事件到forkJoin:

    switchMap(() => forkJoin([rxnsObservable, headCountObservable])),

如果你希望单个事件流再次触发两个请求。

用户回答回答于

查看显示HTTP请求的实际触发器的代码片段会很有帮助,但它很可能是一个在点击时调用函数的UI组件。

解决此问题的方法是使用RxJS 6的Subject接收单击事件。然后使用switchMap取消未完成的请求,以防止backpressure。以下是一个例子:

private clickSubject$: Subject<void> = new Subject();

constructor() {
    this.clickSubject$
        .pipe(switchMap(() => forkJoin([rxnsObservable, headCountObservable])))
        .subscribe((results) => // handling)
}

onClick() {
    this.clickSubject$.next(undefined);
}

如果你有多个要执行http请求的位置,则用this.clickSubject$.next(undefined)将其发送到主题中。

扫码关注云+社区

领取腾讯云代金券