Angular9 防抖優(yōu)化

2020-07-06 15:36 更新

如果你需要發(fā)一個(gè) HTTP 請(qǐng)求來(lái)響應(yīng)用戶的輸入,那么每次擊鍵就發(fā)送一個(gè)請(qǐng)求的效率顯然不高。最好等用戶停止輸入后再發(fā)送請(qǐng)求。這種技術(shù)叫做防抖??梢酝ㄟ^(guò)防抖來(lái)優(yōu)化與服務(wù)器的交互。

考慮下面這個(gè)模板,它讓用戶輸入一個(gè)搜索詞來(lái)按名字查找 npm 包。 當(dāng)用戶在搜索框中輸入名字時(shí),PackageSearchComponent 就會(huì)把這個(gè)根據(jù)名字搜索包的請(qǐng)求發(fā)給 npm web API

Path:"app/package-search/package-search.component.html (search)" 。

<input (keyup)="search($event.target.value)" id="name" placeholder="Search"/>


<ul>
  <li *ngFor="let package of packages$ | async">
    <b>{{package.name}} v.{{package.version}}</b> -
    <i>{{package.description}}</i>
  </li>
</ul>

這里,keyup 事件綁定會(huì)把每次擊鍵都發(fā)送給組件的 search() 方法。下面的代碼片段使用 RxJS 的操作符為這個(gè)輸入實(shí)現(xiàn)了防抖。

Path:"app/package-search/package-search.component.ts (excerpt)" 。

withRefresh = false;
packages$: Observable<NpmPackageInfo[]>;
private searchText$ = new Subject<string>();


search(packageName: string) {
  this.searchText$.next(packageName);
}


ngOnInit() {
  this.packages$ = this.searchText$.pipe(
    debounceTime(500),
    distinctUntilChanged(),
    switchMap(packageName =>
      this.searchService.search(packageName, this.withRefresh))
  );
}


constructor(private searchService: PackageSearchService) { }

searchText$ 是來(lái)自用戶的搜索框值的序列。它被定義為 RxJS Subject 類型,這意味著它是一個(gè)多播 Observable,它還可以通過(guò)調(diào)用 next(value) 來(lái)自行發(fā)出值,就像在 search() 方法中一樣。

除了把每個(gè) searchText 的值都直接轉(zhuǎn)發(fā)給 PackageSearchService 之外,ngOnInit() 中的代碼還通過(guò)下列三個(gè)操作符對(duì)這些搜索值進(jìn)行管道處理,以便只有當(dāng)它是一個(gè)新值并且用戶已經(jīng)停止輸入時(shí),要搜索的值才會(huì)抵達(dá)該服務(wù)。

  • debounceTime(500) - 等待用戶停止輸入(本例中為 1/2 秒)。

  • distinctUntilChanged() - 等待搜索文本發(fā)生變化。

  • switchMap() - 將搜索請(qǐng)求發(fā)送到服務(wù)。

這些代碼把 packages$ 設(shè)置成了使用搜索結(jié)果組合出的 Observable 對(duì)象。 模板中使用 AsyncPipe 訂閱了 packages$,一旦搜索結(jié)果的值發(fā)回來(lái)了,就顯示這些搜索結(jié)果。

使用 switchMap() 操作符

switchMap() 操作符接受一個(gè)返回 Observable 的函數(shù)型參數(shù)。在這個(gè)例子中,PackageSearchService.search 像其它數(shù)據(jù)服務(wù)方法那樣返回一個(gè) Observable。如果先前的搜索請(qǐng)求仍在進(jìn)行中 (如網(wǎng)絡(luò)連接不良),它將取消該請(qǐng)求并發(fā)送新的請(qǐng)求。

請(qǐng)注意,switchMap() 會(huì)按照原始的請(qǐng)求順序返回這些服務(wù)的響應(yīng),而不用關(guān)心服務(wù)器實(shí)際上是以亂序返回的它們。

如果你覺得將來(lái)會(huì)復(fù)用這些防抖邏輯, 可以把它移到單獨(dú)的工具函數(shù)中,或者移到 PackageSearchService 中。

以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)