2017-06-05 61 views
1

我目前正在做的是設置輸入雙向綁定到appRequestParams.appName,並在每個keyup事件中,將調用fetchApps()方法。防跳輸入到http服務調用

我正在嘗試消除輸入,以便它不會立即在每個keyup上觸發後端http請求。

我已經閱讀了關於如何做這件事的方法,以及我在這裏所得到的結果。

HTML

<input #searchBox id="search" mdInput placeholder="Search by list of apps" (keyup)="search(searchBox.value)" /> 

打字稿

private searchTerms = new Subject<string>(); 

search(value: string): void { 
     this.searchTerms.next(value); 
    } 


fetchApps() { 
     this.appService.query({ 
      appName: this.appRequestParams.appName ? this.appRequestParams.appName : null, 
     }).subscribe(
      (res: ResponseWrapper) => this.onSuccess(res.json, res.headers), 
      (res: ResponseWrapper) => this.onError(res.json) 
     ); 
    } 


ngOnInit() { 
     this.searchTerms 
     .debounceTime(300) 
     .distinctUntilChanged() 
     .switchMap((value: string) => { 
      this.appRequestParams.appName = value; 
      this.fetchApps(); 
     }); 
    } 

錯誤對.switchMap()行:你的代碼

Argument of type '(value: string) => void' is not assignable to parameter of type '(value: string, index: number) => ObservableInput<{}>'. 
    Type 'void' is not assignable to type 'ObservableInput<{}>'. 
+0

問題出在返回類型。請檢查您的服務的退貨類型 – Gautam

回答

4

去抖相關的部分是好的。問題是你不能在不返回另一個observable的情況下調用switchMap。

SwitchMap基本上將Observable的最後一個發射值轉換爲另一個Observable,給出了對http請求的自動驗證的額外能力。

嘗試以下方法:

private searchTerms = new Subject<string>(); 

search(value: string): void { 
     this.searchTerms.next(value); 
    } 


fetchApps() { 
     this.appService.query({ 
      appName: this.appRequestParams.appName ? this.appRequestParams.appName : null, 
     }); 
    } 


ngOnInit() { 
     this.searchTerms 
     .debounceTime(300) 
     .distinctUntilChanged() 
     .switchMap((value: string) => { 
      this.appRequestParams.appName = value; 
      return this.fetchApps(); 
     }).subscribe(
      (res: ResponseWrapper) => this.onSuccess(res.json, res.headers), 
      (res: ResponseWrapper) => this.onError(res.json) 
     ); 
    } 

一個典型的例子被關聯到在ActivatedRoute路由參數。考慮以下幾點:

@Injectable() 
    export class FooService{ 
    .. 
    getFooById(id:string): Observable<FooInterface>{ 
     return this.http.get('endpoint/${id}') 
     .map(res=>res.json()) 
     .catch(_throw(error)); 
    } 
    } 

現在我們轉到像根/富/ 10980312,其中最後一部分是在路由

@Component({...}) 
class FooPreviewComponent{ 
    data: FooInterface; 
    constructor(
    private _route: ActivatedRoute, 
    private _service: FooService) { 
    this._route.params 
     .switchMap(params=> 
      this._service.getFooById(params.id))//switchMap return type is Observable<FooInterface> because of the definition of getFooById 
     .subscribe(fooElement => this.data); //intellisense will detect the type of fooElement as FooInterface because of the return type of switchmap 
    } 
} 

定義爲:id在該HTTP正在處理的時間,如果我們現在導航到root/foo/1312313,以前的請求將被自動取消。

switchMap還有其他的應用程序,但它需要一些內部/外部可觀察元素的一些內部理解。

您的解決方案效率低下,因爲您正在訂閱去抖輸入值以及由它們觸發的http響應,但您對第一個操作什麼都沒有做,當時您只是想要訂閱http響應。因此,您可以通過正確使用switchMap來保存其中的一個訂閱。

+0

完美。 'fetchApps()'方法需要稍作修改。需要'返回this.appService.query' –

-1

我最終使用這個,它完美的作品。

this.searchTerms 
    .debounceTime(300) 
    .distinctUntilChanged() 
    .switchMap(
    (term) => { 
     console.log('Term:' + term); 
     this.appRequestParams.appName = term; 
     this.fetchApps(); 
     return term; 
    }) 
    .subscribe(); 
} 
+0

在我看來,這不是一個真正的智能解決方案 –

+0

@ Jota.Toledo這是一個快速修復。我想了解'switchMap'和'observables'現在如何工作。你的答案是產生同樣的錯誤,因此這個修復。也許你可以闡明爲什麼這不理想? –

+0

我編輯了我的答案,希望它有幫助 –