忽略已取消的可观测的中间排放

时间:2019-07-04 02:52:11

标签: angular rxjs rxjs6

用户可以使用Angular 2 combine three http calls with flatMap? RxJs?这种方法触发搜索,在该搜索中我链接了数量不定的HTTP请求。

这一切都很好,但我想取消旧搜索,如果它们在启动新搜索时仍在运行。像这样:

  • 用户开始搜索A
    • 搜索第1部分开始
    • 搜索第1部分结束
    • 搜索第2部分开始
  • 用户开始搜索B
    • 搜索B第1部分开始
    • 搜索B第1部分结束
    • 搜索B完成
  • 用户看到B的结果(B第1部分)

我能找到的最接近的是switchAll,它确实丢弃/取消了A部分2,但是我将A部分1混入了结果中。注意:仅包括最后完成的零件,因此,如果用户在零件n期间开始新的搜索,则仅包含n - 1(对于n > 1)和n - 2,以及优先级被丢弃。

所以我的问题:

  • 为什么中间结果一起运行?
  • 我如何实现想要的效果?
    • 我可以放弃先前搜索的中间结果吗?
    • 我可以将搜索视为奇异发射吗?

我得到的代码有点混乱,但这是一个粗略的,简化的轮廓:

// User fires this event.
startSearch() {
    this.searchSubject(getUsersCriteria());
}

ngOnInit() {
    // The event is transformed into a search request.
    this.searchSubject
        .asObservable()
        .pipe(
            map((criteria) => search(criteria)),
            switchAll(), // FIXME Not sufficient.
            tap((results) => this.setResults(results))
        )
        .subscribe();
}

/**
 * Execute the search and return the results.
 **/
search(criteria): Observable<Result[]> {
    return this.http.get('https://proprietary.com/endpoint', criteria)
        .pipe(flatMap((results) => {
            // Process results. Conditionally continue.
            if (done()) return of(results);
            else return search(criteria.nextCriteria())
                .pipe(map((moreResults) => [...results, ...moreResults]));
        });
}

注意:目前使用的是RxJS 6。

2 个答案:

答案 0 :(得分:0)

不确定是否可行,但是您可以尝试传入额外的参数作为结果集的起始值。 searchSubject触发时,所有空的结果集[]都会被传递到递归链中。

ngOnInit() {
    // The event is transformed into a search request.
    this.searchSubject
        .asObservable()
        .pipe(
            switchMap((criteria) => search(criteria,[])),
            tap((results) => this.setResults(results))
        )
        .subscribe();
}


/**
 * Execute the search and return the results.
 **/
search(criteria,resultSet): Observable<Result[]> {
    return this.http.get('https://proprietary.com/endpoint', criteria)
        .pipe(flatMap((results) => {
            // Process results. Conditionally continue.
            if (done()) return of(resultSet);                
            return search(criteria.nextCriteria(),resultSet.concat(results))   
        });
}

答案 1 :(得分:0)

一个过分热情的HTTP拦截器正在返回第一个(已取消)搜索以及(错误地)第二个搜索的结果。

仔细检查HTTP拦截器。