首页 > 解决方案 > 如何处理 rxjs 和 angular 5 中的 Observables,bootstrap typeahead 实现的问题

问题描述

我正在尝试在角度 5 中实现自动完成(引导输入)。

经过几次代码重构,我得到了迄今为​​止最好的结果。但是在发出新值(在输入中输入新术语)之后,它出现了这个错误......

TypeError: You provided 'undefined' where a stream was expected. You can provide an Observable, Promise, Array, or Iterable.
at Object.subscribeToResult (subscribeToResult.js:74)
at SwitchMapSubscriber.push../node_modules/rxjs/operators/switchMap.js.SwitchMapSubscriber._innerSub (switchMap.js:103)
at SwitchMapSubscriber.push../node_modules/rxjs/operators/switchMap.js.SwitchMapSubscriber._next (switchMap.js:96)
at SwitchMapSubscriber.push../node_modules/rxjs/Subscriber.js.Subscriber.next (Subscriber.js:90)
at DistinctUntilChangedSubscriber.push../node_modules/rxjs/operators/distinctUntilChanged.js.DistinctUntilChangedSubscriber._next (distinctUntilChanged.js:103)
at DistinctUntilChangedSubscriber.push../node_modules/rxjs/Subscriber.js.Subscriber.next (Subscriber.js:90)
at DebounceTimeSubscriber.push../node_modules/rxjs/operators/debounceTime.js.DebounceTimeSubscriber.debouncedNext (debounceTime.js:98)
at AsyncAction.dispatchNext (debounceTime.js:114)
at AsyncAction.push../node_modules/rxjs/scheduler/AsyncAction.js.AsyncAction._execute (AsyncAction.js:111)
at AsyncAction.push../node_modules/rxjs/scheduler/AsyncAction.js.AsyncAction.execute (AsyncAction.js:86)

这是我的代码:

private searchTerm = new Subject<string>();
public termsArray: any = [];
constructor(private apiService: DataService){
       const result$ = this.searchTerm
       .debounceTime(100)
       .distinctUntilChanged()
       .switchMap(term => this.apiService.getSearchTest(term))
           .subscribe(result => {
                      this.termsArray = result.suggestions as Array<any>;
                      console.log(this.termsArray);
                      }
                      , err => console.log(err))
}

autocompleteTest = (text$: Observable<string>) =>
    text$.pipe(
        debounceTime(300),
        distinctUntilChanged(),
        map(term => term.length < 1 ? []
            : this.termsArray
                .filter(v => v.toLowerCase().indexOf(term.toLowerCase()) > -1)
                .slice(0, 10))
        )

onKeyUpSearch(searchText: string){
    if (searchText !== "") this.searchTerm.next(searchText);
}

标签: angulartwitter-bootstraprxjsbootstrap-typeahead

解决方案


通常你有两件事

private searchTerm = new Subject<string>();
observableSearchTerm=this.searchTerm.asObservable()

您在 searchTerm 上创建“下一个”,但从 observable 订阅

onKeyUpSearch(searchText: string){
    if (searchText !== "") this.searchTerm.next(searchText);
}
//But subscribe to the "Observable" 
 this.observableSearchTerm
   .debounceTime(100)
   .distinctUntilChanged()
   .switchMap(term => this.apiService.getSearchTest(term))
       .subscribe(result => {
          ...
   }

注意 1:在 RxJs 6 (Angular 6) 中,您必须使用管道更改代码

 this.observableSearchTerm.pipe(
   debounceTime(100),
   distinctUntilChanged(),
   switchMap(term => this.apiService.getSearchTest(term))
 ).subscribe(result => {
          ...
 }

NOTE2:您可以使用 FromControl 并直接订阅值更改

//In .html
<input type="text" [formControl]="control">

//In .ts
control:FormControl=new FormControl()  //Define the control
//..after in ngOnInit
ngOnInit()
{
   this.control.valueChanges.pipe(
      debounceTime(100),
      distinctUntilChanged(),
      switchMap(term => this.apiService.getSearchTest(term)
   ).subscribe(result=>{
     ....
   })
 }

stackblitz


推荐阅读