switchMap不会取消以前的http请求

时间:2018-11-17 20:11:34

标签: javascript typescript rxjs

switchMap不会取消以前的http请求。还尝试了exhaustMap但没有帮助。这是相同https://gist.github.com/saiumesh-letznav/a33ac54444ba707b9dbb172271b518fe

的要点
import { Subject } from 'rxjs';
import { switchMap } from 'rxjs/operators';
import Axios from 'axios';

const baseUrl =
  'https://api.github.com/search/repositories?q=golang+language:go&sort=stars&order=desc';

class GitService {
  private $obs: Subject<void> = new Subject();

  constructor() {
    this.$obs
      .pipe(switchMap((_) => Axios.get(baseUrl)))
      // tslint:disable-next-line:no-console
      .subscribe((res) => console.log({ res }));
  }

  public getGOlangRepos() {
    this.$obs.next();
  }
}

const instance = new GitService();

instance.getGOlangRepos();
instance.getGOlangRepos();
instance.getGOlangRepos();
instance.getGOlangRepos();

2 个答案:

答案 0 :(得分:2)

如果您要实际取消axios请求(而不是继续执行,而忽略其结果),则不能简单地将mapmap切换到axios.get返回的Promise。承诺是无法取消的,尽管axios支持取消,但是rxjs不知道axios的取消是如何工作的。因此,您需要自己实施取消。

在rxjs之外,您可以通过以下方法发出axios请求,然后稍后将其取消:

const cancelToken = Axios.CancelToken.source();
const promise = Axios.get(someUrl, { cancelToken: cancelToken.token };

// ... then later to cancel it:
cancelToken.cancel();

如果您希望rxjs能够使用此取消逻辑,则需要创建一个自定义的Observable。如果您认为这是您经常会做的事情,建议您将其移入辅助功能。像这样:

function getAsObservable(url) {
  return Observable.create(function(observer) {
    const cancelToken = Axios.CancelToken.source();
    Axios.get(url, { cancelToken: cancelToken.token })
      .then(result => {
        observer.next(result);
        observer.complete();
      }, err => {
        if (axios.isCancel(err)) {
          observer.complete();
        } else {
          observer.error(err);
        }
      })

    return () => cancelToken.cancel();
  });
}

然后您的代码可以变成:

this.$obs
 .pipe(switchMap((_) => getAsObservable(baseUrl)))
 .subscribe((res) => console.log({ res }));

答案 1 :(得分:-1)

您可以使用debounceTime来避免多次HTTP呼叫,以便在进行HTTP呼叫之前增加延迟。 http调用一旦完成,即使在客户端应用中取消了订阅,服务器也将继续处理它。

例如-下面的代码将在拨打http之前等待500毫秒。

constructor() {
 this.$obs
  .pipe(
     debounceTime(500),
     switchMap((_) => Axios.get(baseUrl))
  )
  // tslint:disable-next-line:no-console
  .subscribe((res) => console.log({ res }));
}