首页 > 解决方案 > 使用 typeahead ngx-bootstrap 合并两个调用并显示结果?

问题描述

我将首先向您展示工作代码:

<input [formControl]="search" 
       [typeahead]="suggestions" 
       typeaheadOptionField="name"   
       (typeaheadOnSelect)="onSelectedDriver($event)">


ngOnInit(){
  public autocompleteValue() {
    this.search.valueChanges.subscribe(
      (selectedValue) => {
        this.searchVal(selectedValue)
      }
    );
  }
}


  public searchVal(val: string) {
    this.suggestions = (new Observable((observer: Observer<string>) => {
      observer.next(val);
    })).pipe(
      switchMap((query: string) => {
        if (query) {
          switch (this.serverApi) {
            case 'Driver':
              return this.getAllDrivers(query); 

            default:
              break;
          }
        }
        return of([]);
      })
    );
  }

和:

  getAllDrivers(query: string) {
    return this.accountsService.getDrivers(query)
      .pipe(
        map((data: any) => {
          data.body?.forEach((driver: IDriver) => {
            driver.name = `${driver.firstName} ${driver.lastName}`
          });
          return data.body || [];
        }),
        tap(() => noop, err => {
          this.errorMessage = err && err.message || 'Something goes wrong';
        })
      )
  }

这行得通。

但我需要扩展功能。

我需要一个扩展来将两个 api 调用合并为一个并返回结果。

我要这样做,但没有用 forkJoin 预先输入..

   this.search.valueChanges.subscribe(val => { 
      let driverLoad = this.service.searchDrivers(val, [{ name: 'name', value: val }]);
      let affiliateLoad = this.service.searchAffiliates(val, [{ name: 'name', value: val }]) 
      forkJoin([driverLoad, affiliateLoad, travelAgenciesLoad]).subscribe(resultsOfSearch => {
        let driverArr = resultsOfSearch[0].body;
        let affiliateArr = resultsOfSearch[1].body; 
        this.autoCompleteResults = [...driverArr as [], ...affiliateArr as []];
        return this.autoCompleteResults
      })
    });

我现在不知道是否适合这个工作。

我如何结合它并返回结果?

标签: angulartypescriptrxjstypeaheadngx-bootstrap

解决方案


分叉加入

forkJoin 仅在所有源 observables 完成时才发出一个值。因此 - 它可能不适合您的情况。

forkJoin 文档

等待 Observables完成,然后组合它们发出的最后一个值;如果传递了一个空数组,则立即完成。

在您的代码中,在可观察的 driverLoad、affiliateLoad 和 travelAgenciesLoad 都完成之前,forkJoin 不会发出值。

结合最新

如果你的三个 Observable 是连续的数据流,需要在它们完成之前进行组合,一个更好的操作符是 combineLatest:

结合最新文档

每当任何输入 Observable 发出一个值时,它都会使用来自所有输入的最新值计算一个公式,然后发出该公式的输出。

//Define observables before subscribing to valueChanges
let driverLoad = this.service.searchDrivers(val, [{ name: 'name', value: val }]);
let affiliateLoad = this.service.searchAffiliates(val, [{ name: 'name', value: val }]) 
let combinationObservable$: Observable<any>;

// when valueChanges emits a value, find the latest emitted value from driverLoad,
// affiliateLoad, and travelAgenciesLoad
this.search.valueChanges.subscribe(val => {
  combinationObservable$ = combineLatest([driverLoad, affiliateLoad, travelAgenciesLoad]); 
}

//subscribe to combination Observable outside of the valueChanges subscription
combinationObservable$.subscribe(value => {
  console.log(value);
  this.autoCompleteResults = value;
});

这是我使用combineLatest操作符模拟你的 observables 的 StackBlitz。


推荐阅读