溫馨提示:本文使用 ChatGPT 潤(rùn)色凑队。
參考鏈接:
RxJS:https://rxjs.tech/guide/overview
Promise:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Promise
服務(wù)器端事件發(fā)送(
SSE
):https://docs.nestjs.cn/9/techniques?id=%e6%9c%8d%e5%8a%a1%e5%99%a8%e7%ab%af%e4%ba%8b%e4%bb%b6%e5%8f%91%e9%80%81
前言
最近在研究如何在 Nest.js 中實(shí)現(xiàn) SSE粮揉,結(jié)果發(fā)現(xiàn)需要使用 RxJS辛友。由于需要執(zhí)行異步操作碌秸,不可避免地使用了 Promise廉丽。因此较幌,我研究了一下如何在 RxJS 中使用 Promise净响,并有一些心得少欺,現(xiàn)在特此記錄。
SSE
服務(wù)器端事件發(fā)送(SSE
)是一個(gè)服務(wù)器推送技術(shù)别惦,用來使客戶端在HTTP
連接下自動(dòng)接收服務(wù)器更新消息狈茉。每個(gè)消息以一個(gè)由一對(duì)新行符號(hào)作為結(jié)束的文字塊發(fā)送(參見這里)。
如果要在 Nest.js 中使用 SSE掸掸, 需要返回一個(gè)Observable
流氯庆,例如:
export interface MessageEvent {
data: string | object;
id?: string;
type?: string;
retry?: number;
}
/// 省略其他部分代碼
@Sse('sse')
sse(): Observable<MessageEvent> {
return interval(1000).pipe(map((_) => ({ data: { hello: 'world' } })));
}
這樣就可以實(shí)現(xiàn)一個(gè)每秒發(fā)送一次 { hello: 'world' }
的 SSE 路由。
在瀏覽器端/客戶端只要如下使用即可:
const eventSource = new EventSource('/sse');
eventSource.onmessage = ({ data }) => {
console.log('New message', JSON.parse(data));
};
使用 Promise
在具體的業(yè)務(wù)邏輯中扰付,返回的 Observable 里必然會(huì)包含異步邏輯堤撵,其中就有可能用到 Promise。
處理單個(gè) Promise
處理單個(gè) Promise 非常簡(jiǎn)單羽莺,只需要使用 RxJS 提供的 from
操作符即可:
import { from } from 'rxjs';
const promise = new Promise((resolve, reject) => {
resolve('ok')
})
const observable = from(promise)
observable.subscribe((e) => console.log(e)) // ok
通過 from
操作符实昨,可以直接獲取到 Promise 的 resolve 值。
處理多個(gè) Promise
但在更多情況下盐固,Observable 中會(huì)返回多個(gè) Promise荒给,例如:
@Sse('sse')
sse(): Observable<MessageEvent> {
return interval(1000)
.pipe(
map(async () => {
const data = await client.get("key") // 進(jìn)行異步操作
return {
data
}
}),
)
}
上述代碼會(huì)每秒執(zhí)行一次異步操作,然后返回一個(gè) Promise刁卜,此時(shí)就得到了多個(gè) Promise志电。
在這種情況下,要獲取 Promise 的 resolve 值就會(huì)稍微麻煩些蛔趴,需要使用mergeAll
操作符 來將高階 Observable 轉(zhuǎn)換為一階 Observable挑辆。,從而獲取到 Promise 的 resolve 值。
這其中的原理就在于 Promise 實(shí)際上也會(huì)被視為一個(gè) Observable 鱼蝉,因此多個(gè) Promise 就構(gòu)成了高階 Observable洒嗤,故需要用 mergeAll
操作符來展平 Promise 數(shù)組。
@Sse('sse')
sse(): Observable<MessageEvent> {
return interval(1000)
.pipe(
map(async () => {
const data = await client.get("key") // 進(jìn)行異步操作
return {
data
}
}),
mergeAll(),
tap((e)=>{
console.log(e) // 此時(shí)就能看到 Promise的resolve 值了魁亦,e 的類型為原始值渔隶,而不是 Promise包裝后的值
})
)
}
總結(jié)
Promise 和 Observable 都是 JavaScript 中常用的異步編程工具。
Promise 簡(jiǎn)單易用吉挣,常用于處理單個(gè)異步操作派撕,但當(dāng)需要同時(shí)處理多個(gè)異步操作時(shí)婉弹,Promise 就顯得力不從心了睬魂。
Observable 相對(duì)于 Promise 具有更多的特性和功能,能夠處理多個(gè)異步操作并發(fā)執(zhí)行镀赌,包括錯(cuò)誤處理氯哮、取消操作等。在 RxJS 中商佛,Observable 是核心概念喉钢,提供了許多操作符來處理各種異步操作,例如過濾良姆、映射肠虽、合并等。Observable 是一個(gè)被廣泛應(yīng)用于前端開發(fā)中的工具玛追。
在處理多個(gè) Promise 的情況下税课,可以將多個(gè) Promise 封裝到一個(gè) Observable 中,然后使用 mergeAll 操作符將高階 Observable 轉(zhuǎn)換為一階 Observable痊剖,以便獲取 Promise 的 resolve 值韩玩。 總之,當(dāng)需要處理多個(gè)異步操作時(shí)陆馁,Observable 是一種更為強(qiáng)大和靈活的異步編程工具找颓,而 Promise 則是一種更為簡(jiǎn)單和易用的異步編程工具,需要根據(jù)實(shí)際情況選擇適合的工具來處理異步操作叮贩。
本文作者:草梅友仁
本文地址:https://blog.cmyr.ltd/archives/84a41459.html
版權(quán)聲明:轉(zhuǎn)載請(qǐng)注明出處击狮!