switchMap 不会取消之前的 http 请求

1 javascript rxjs typescript

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();
Run Code Online (Sandbox Code Playgroud)

Nic*_*wer 6

如果你想真正取消 axios 请求(而不是让它继续但忽略它的结果),那么你不能简单地切换到 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();
Run Code Online (Sandbox Code Playgroud)

如果你想让 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();
  });
}
Run Code Online (Sandbox Code Playgroud)

然后你的代码可以变成:

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