switchMap和debounceTime取消挂起

时间:2019-07-31 12:19:38

标签: angular typescript rxjs observable

我有一种方法可以根据搜索词搜索员工的信息。

this._sub.pipe(
    debounceTime(500),
    filter(x => !!x),
    distinctUntilChanged(),
    switchMap(this.getResults.bind(this))
).subscribe((d: IDisplayEmp[]) => {
    console.log('RES', d)
    this.displayResults = d;
});

this._sub.next('mySearchTerm');

这很好用,如果发出新的API调用,则先前的API调用将被取消。但是问题来了。

仅在发出反跳后才取消活动的API调用。如果在反跳等待期间返回了活动的API调用,它仍会触发我的订阅。

我了解这是因为取消仅发生在switchmap的范围内。

是否可以对此进行重构,以便如果防抖动功能正在等待输入停止,它将取消所有未决的API调用?

可能是一种幼稚的方法,但是我尝试了如下所示的方法,它会发出值,但是现在没有反跳效果。

this._sub.pipe(
    filter(x => !!x),
    distinctUntilChanged(),
    switchMap((x) => {
        return of(x)
            .pipe(
                debounceTime(500),
                this.getResults.bind(this)
            );
    })
).subscribe((d: IDisplayEmp[]) => {
    console.log('RES', d)
    this.displayResults = d;
});

感谢您的帮助。

4 个答案:

答案 0 :(得分:2)

只要takeUntil发出,就使用this._sub取消您的请求。

this._sub.pipe(
    debounceTime(500),
    filter(x => !!x),
    distinctUntilChanged(),
    switchMap(searchTerm => this.getResults(searchTerm).pipe(
      takeUntil(this._sub)
    ))
).subscribe((d: IDisplayEmp[]) => {
    console.log('RES', d)
    this.displayResults = d;
});

答案 1 :(得分:1)

我相信这应该对您有用:

使用concat,以便第二次发射等待第一个发射完成。

const getFromAPI = (key: string): Observable<number> => {
    return;
};

const keys: Observable<string> = new Observable();

concat(
    keys.pipe(
        debounceTime(500),
        switchMap(key => getFromAPI(key)),
        take(1)
    )
).subscribe(console.log);

另一个例子:

const getFromAPI = (key: string): Observable<number> => {
    return;
};

const keys: Observable<string> = new Observable();

const debouncedKeys = keys.pipe(debounceTime(500));

concat(
    debouncedKeys.pipe(
        switchMap(key => getFromAPI(key)),
        take(1),
        takeUntil(debouncedKeys)
    )
).subscribe(console.log);

答案 2 :(得分:1)

不确定此处是否需要探索,但您可以将_sub转换为两个可观察值,一个将被反跳并返回原始查询,第二个未被反跳并返回null / undefined。

然后将它们合并并调用switchMap。

未消弹的可观察值应允许您取消呼叫,因为它也会到达切换映射。在这种情况下,switchMap可能返回空值或从不可见。并且只有当值附带的去观察的可观察对象时,才重新创建API调用。

类似的东西吗?

const debounced = this._sub.pipe(debounceTime(500), filter(x => !!x), distinctUntilChanged());
const undebounced = this._sub.pipe(map(_ => undefined));

merge(debounced, undebounced).pipe(
    switchMap(val => {
        if (val) {
            return this.getResults(val);
        } else {
            return never;
        }
    })
);

答案 3 :(得分:0)

可接受的答案应该可以正常工作,但是我想与您分享另一种可以用timer而不是debounceTime来做到这一点的方法:

this._sub.pipe(
    filter(x => !!x),
    distinctUntilChanged(),
    switchMap(val => timer(500).pipe(
        switchMap(() => this.getResults(val))
    ))
).subscribe(...);

现在,如果排放量达到switchMap,则timer及其中的所有内容(包括有效的网络请求)都将被取消,并创建新的timer

>