日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

使用 RxJs Observable 来避免 Angular 应用中的 Promise 使用

發(fā)布時(shí)間:2023/12/19 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 使用 RxJs Observable 来避免 Angular 应用中的 Promise 使用 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

我們通過(guò)一個(gè)具體的例子來(lái)闡述。

考慮您正在構(gòu)建一個(gè)搜索輸入掩碼,該掩碼應(yīng)在您鍵入時(shí)立即顯示結(jié)果。

如果您曾經(jīng)構(gòu)建過(guò)這樣的東西,那么您可能會(huì)意識(shí)到該任務(wù)帶來(lái)的挑戰(zhàn)。

  • 不要在每次擊鍵時(shí)都點(diǎn)擊搜索端點(diǎn)
  • 將搜索端點(diǎn)視為您按請(qǐng)求付費(fèi)。不管它是不是你自己的硬件。我們不應(yīng)該比需要的更頻繁地敲擊搜索端點(diǎn)。基本上我們只想在用戶停止輸入后點(diǎn)擊它,而不是每次擊鍵時(shí)點(diǎn)擊它。

  • 不要在后續(xù)請(qǐng)求中使用相同的查詢(xún)參數(shù)命中搜索端點(diǎn)
  • 假設(shè)您鍵入 foo,停止,鍵入另一個(gè) o,然后立即退格并返回到 foo。這應(yīng)該只是一個(gè)帶有 foo 一詞的請(qǐng)求,而不是兩個(gè),即使我們?cè)谒阉骺蛑杏?foo 后從技術(shù)上講停止了兩次。

    3.處理亂序響應(yīng)

    當(dāng)我們同時(shí)有多個(gè)請(qǐng)求進(jìn)行中時(shí),我們必須考慮它們以意外順序返回的情況。考慮我們首先鍵入 computer,停止,請(qǐng)求發(fā)出,我們鍵入 car,停止,請(qǐng)求發(fā)出。現(xiàn)在我們有兩個(gè)正在進(jìn)行的請(qǐng)求。不幸的是,在為 car 攜帶結(jié)果的請(qǐng)求之后,為 computer 攜帶結(jié)果的請(qǐng)求又回來(lái)了。這可能是因?yàn)樗鼈冇刹煌姆?wù)器提供服務(wù)。如果我們不正確處理此類(lèi)情況,我們最終可能會(huì)顯示 computer 的結(jié)果,而搜索框會(huì)顯示 car.

    我們將使用免費(fèi)和開(kāi)放的維基百科 API 來(lái)編寫(xiě)一個(gè)小演示。

    為簡(jiǎn)單起見(jiàn),我們的演示將只包含兩個(gè)文件:app.ts 和 wikipedia-service.ts。 不過(guò),在現(xiàn)實(shí)世界中,我們很可能會(huì)將事情進(jìn)一步拆分。

    讓我們從一個(gè)基于 Promise 的實(shí)現(xiàn)開(kāi)始,它不處理任何描述的邊緣情況。

    這就是我們的 WikipediaService 的樣子。

    使用了 jsonp 這個(gè) Angular HTTP 服務(wù):

    上圖將來(lái)自 angular/http 庫(kù)中的 jsonp 返回的對(duì)象,使用 toPromise 方法轉(zhuǎn)換成了 promise.

    簡(jiǎn)單地說(shuō),我們正在注入 Jsonp 服務(wù),以使用給定的搜索詞針對(duì)維基百科 API 發(fā)出 GET 請(qǐng)求。 請(qǐng)注意,我們調(diào)用 toPromise 是為了從 Observable<Response> 到 Promise<Response>。 通過(guò) then-chaining 我們最終得到一個(gè) Promise<Array<string>> 作為我們搜索方法的返回類(lèi)型。

    到目前為止一切順利,讓我們看看保存我們的 App 組件的 app.ts 文件。

    看一下 wiki service 如何被消費(fèi)的:

    這里也沒(méi)什么驚喜。 我們注入我們的 WikipediaService 并通過(guò)搜索方法向模板公開(kāi)它的功能。 模板簡(jiǎn)單地綁定到 keyup 并調(diào)用 search(term.value) 利用 Angular 的很棒的模板引用功能。

    我們解開(kāi) WikipediaService 的搜索方法返回的 Promise 的結(jié)果,并將其作為一個(gè)簡(jiǎn)單的字符串?dāng)?shù)組公開(kāi)給模板,這樣我們就可以讓 *ngFor 循環(huán)遍歷它并為我們構(gòu)建一個(gè)列表。

    不幸的是,這個(gè)實(shí)現(xiàn)沒(méi)有解決我們想要處理的任何所描述的邊緣情況。 讓我們重構(gòu)我們的代碼,使其符合預(yù)期的行為。

    讓我們更改我們的代碼,不要在每次擊鍵時(shí)敲擊端點(diǎn),而是僅在用戶停止輸入 400 毫秒時(shí)發(fā)送請(qǐng)求。 這就是 Observables 真正閃耀的地方。 Reactive Extensions (Rx) 提供了廣泛的運(yùn)算符,讓我們可以改變 Observables 的行為并創(chuàng)建具有所需語(yǔ)義的新 Observables。

    為了揭示這樣的超能力,我們首先需要獲得一個(gè) Observable<string> ,它攜帶用戶輸入的搜索詞。 我們可以利用 Angular 的 formControl 指令,而不是手動(dòng)綁定到 keyup 事件。 要使用此指令,我們首先需要將 ReactiveFormsModule 導(dǎo)入到我們的應(yīng)用程序模塊中。

    導(dǎo)入后,我們可以在模板中使用 formControl 并將其設(shè)置為名稱(chēng)“term”。

    <input type="text" [formControl]="term"/>

    在我們的組件中,我們從@angular/form 創(chuàng)建了一個(gè) FormControl 的實(shí)例,并將其公開(kāi)為組件上名稱(chēng) term 下的一個(gè)字段。

    在幕后,術(shù)語(yǔ)會(huì)自動(dòng)公開(kāi)一個(gè) Observable<string> 作為我們可以訂閱的屬性 valueChanges。 現(xiàn)在我們有了一個(gè) Observable<string>,馴服用戶輸入就像在我們的 Observable 上調(diào)用 debounceTime(400) 一樣簡(jiǎn)單。 這將返回一個(gè)新的 Observable<string>,它只會(huì)在 400 毫秒內(nèi)沒(méi)有新值出現(xiàn)時(shí)才發(fā)出新值。

    這個(gè)新的對(duì)象會(huì)在我們期望的時(shí)間間隔之后,才會(huì)發(fā)生新值。至于如何控制時(shí)間間隔,對(duì)前端開(kāi)發(fā)人員來(lái)說(shuō)是一個(gè)黑盒子。

    export class App {items: Array<string>;term = new FormControl();constructor(private wikipediaService: WikipediaService) {this.term.valueChanges.debounceTime(400).subscribe(term => this.wikipediaService.search(term).then(items => this.items = items));} }

    正如我們所說(shuō),對(duì)我們的應(yīng)用程序已經(jīng)顯示結(jié)果的搜索詞發(fā)出另一個(gè)請(qǐng)求將是一種資源浪費(fèi)。幸運(yùn)的是,Rx 簡(jiǎn)化了許多幾乎不需要提及的操作。為了實(shí)現(xiàn)所需的行為,我們所要做的就是在我們調(diào)用 debounceTime(400) 之后立即調(diào)用 distinctUntilChanged 運(yùn)算符。同樣,我們將返回一個(gè) Observable<string> ,但它忽略了與前一個(gè)相同的值。

    處理無(wú)序響應(yīng)

    處理無(wú)序響應(yīng)可能是一項(xiàng)棘手的任務(wù)。基本上,我們需要一種方法來(lái)表示,一旦我們發(fā)出新請(qǐng)求,我們就不再對(duì)之前進(jìn)行中的請(qǐng)求的結(jié)果感興趣。換句話說(shuō):一旦我們開(kāi)始一個(gè)新的請(qǐng)求,就取消所有先前的請(qǐng)求。正如我在開(kāi)頭簡(jiǎn)要提到的,Observables 是一次性的,這意味著我們可以取消訂閱它們。

    這是我們想要更改 WikipediaService 以返回 Observable<Array<string>> 而不是 Promise<Array<string>> 的地方。這就像刪除 toPromise 并使用 map 而不是 then 一樣簡(jiǎn)單。

    search (term: string) {var search = new URLSearchParams()search.set('action', 'opensearch');search.set('search', term);search.set('format', 'json');return this.jsonp.get('http://en.wikipedia.org/w/api.php?callback=JSONP_CALLBACK', { search }).map((response) => response.json()[1]); }

    現(xiàn)在我們的 WikipediaSerice 返回一個(gè) Observable 而不是 Promise,我們只需要在我們的 App 組件中將 then 替換為 subscribe 。

    this.term.valueChanges.debounceTime(400).distinctUntilChanged().subscribe(term => this.wikipediaService.search(term).subscribe(items => this.items = items));

    但是現(xiàn)在我們有兩個(gè) subscribe 調(diào)用。 這是不必要的冗長(zhǎng),通常是需要代碼重構(gòu)的標(biāo)志。 好消息是,現(xiàn)在搜索返回一個(gè) Observable<Array>,我們可以簡(jiǎn)單地使用 flatMap 通過(guò)組合 Observables 來(lái)將 Observable 投影到所需的 Observable<Array> 中。

    this.term.valueChanges.debounceTime(400).distinctUntilChanged().flatMap(term => this.wikipediaService.search(term)).subscribe(items => this.items = items);

    你可能想知道 flatMap 是做什么的,為什么我們不能在這里使用 map。

    答案很簡(jiǎn)單。 map 操作符需要一個(gè)函數(shù),它接受一個(gè)值 T 并返回一個(gè)值 U。例如一個(gè)接受一個(gè)字符串并返回一個(gè)數(shù)字的函數(shù)。 因此,當(dāng)您使用 map 時(shí),您會(huì)從 Observable<T> 獲得一個(gè) Observable<U>。 但是,我們的搜索方法本身會(huì)生成一個(gè) Observable。 因此,來(lái)自我們?cè)?distinctUntilChanged 之后的 Observable,map 會(huì)將我們帶到 Observable<Observable<Array>。 這不是我們想要的。

    另一方面, flatMap 運(yùn)算符需要一個(gè)函數(shù),它接受一個(gè) T 并返回一個(gè) Observable<U> 并為我們生成一個(gè) Observable<U>。

    注意:這并不完全正確,但它有助于簡(jiǎn)化。

    這完全符合我們的情況。 我們有一個(gè) Observable<string>,然后使用一個(gè)函數(shù)調(diào)用 flatMap,該函數(shù)接受一個(gè)字符串并返回一個(gè) Observable<Array<string>>。

    現(xiàn)在我們已經(jīng)掌握了語(yǔ)義,還有一個(gè)小技巧可以用來(lái)節(jié)省一些打字的時(shí)間。 我們可以讓 Angular 直接在模板中為我們解包,而不是手動(dòng)訂閱 Observable。 我們要做的就是在我們的模板中使用 AsyncPipe 并公開(kāi) Observable<Array<string>> 而不是 Array<string>。

    @Component({selector: 'my-app',template: `<div><h2>Wikipedia Search</h2><input type="text" [formControl]="term"/><ul><li *ngFor="let item of items | async">{{item}}</li></ul></div>` }) export class App {items: Observable<Array<string>>;term = new FormControl();constructor(private wikipediaService: WikipediaService) {this.items = this.term.valueChanges.debounceTime(400).distinctUntilChanged().switchMap(term => this.wikipediaService.search(term));} }

    更多Jerry的原創(chuàng)文章,盡在:“汪子熙”:

    總結(jié)

    以上是生活随笔為你收集整理的使用 RxJs Observable 来避免 Angular 应用中的 Promise 使用的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。