淺淡 RxJS WebSocket

引言

中后臺儀表盤是一個非常復(fù)雜悔耘,特別是當(dāng)需要全面屏運用時,數(shù)據(jù)的實時性需求非常高所意。WebSocket 不管在什么環(huán)境中使用其實都是非常簡單淮逊,各現(xiàn)代瀏覽器實現(xiàn)標(biāo)準(zhǔn)都很統(tǒng)一催首,而且接口也足夠簡單。

即便是在 Angular 也是如此泄鹏,只需要簡單幾行代碼就能使用 WebSocket郎任。

const ws = new WebSocket('wss://echo.websocket.org');
ws.onmessage = (e) => {
  console.log('message', e);
}

若需要向服務(wù)端發(fā)送消息,則:

ws.send(`content`);

在 Angular 里絕大多數(shù)的人都會根據(jù)上述代碼進一步拓展备籽,比如統(tǒng)一消息解析舶治、錯誤處理、多路復(fù)用等车猬,并最終將其封裝成一個服務(wù)類霉猛。

事實上,RxJS 也包裹了一個 WebSocket Subject珠闰,位于 rxjs/websocket惜浅。

如何使用

假如將上面的示例使用 RxJS 來寫,則:

import { webSocket, WebSocketSubject } from 'rxjs/webSocket';

const ws = webSocket('wss://echo.websocket.org');

ws.subscribe(res => {
  console.log('message', res);
});

ws.next(`content`);

webSocket 是一個工廠函數(shù)伏嗜,所生產(chǎn)出來的 WebSocketSubject 對象可被多次訂閱坛悉,若未訂閱或取消最后一個訂閱時都會導(dǎo)致 WebSocket 連接中斷,當(dāng)再一次訂閱時會重新自動連接承绸。

WebSocketSubjectConfig

webSocket 除了接收字符串(WebSocket服務(wù)遠程地址)外裸影,還允許指定更復(fù)雜的配置項。

默認情況下军熏,消息是使用 JSON.parseJSON.stringify 對消息格式序列化和反序列化操作轩猩,所以不管消息發(fā)送或接收都以 JSON 為準(zhǔn),可通過 serializer荡澎、deserializer 屬性來改變均践。

若需要關(guān)心 WebSocket 什么時候開始或結(jié)束(closeObserver),則:

const open$ = new Subject();
const ws = webSocket({
  url: 'wss://echo.websocket.org',
  openObserver: open$
});
// 訂閱打開事件
open$.subscribe(() => {});

消息

WebSocketSubject 也是 Subject 的變體之一衔瓮,因此訂閱它表示接收消息浊猾,反之則利用 nextcomplete热鞍、error 來維護消息的推送。

  • 使用 next 來發(fā)送消息
  • 使用 complete 會嘗試檢測是否最后一個訂閱衔彻,若是將會關(guān)閉連接
  • 使用 error 相當(dāng)于原始 close 方法且必須提供 { code: number, reason?: string} 參數(shù)薇宠,注意 code 務(wù)必遵守取值范圍

可被重放

調(diào)用 next 發(fā)送消息時若 WebSocket 連接中斷(例如:沒人訂閱時),消息會被緩存當(dāng)下一次重新連接以后會按順序發(fā)送艰额。這對于異步世界里非常方便澄港,我們只需要確保 Angular 啟動前初始化好 WebSocket 不管什么時候訂閱接收消息,都可以隨時發(fā)送也無須等待柄沮。

事實上這一點是 RxJS WebSocket 默認情況下是通過 webSocket 所生產(chǎn)的 WebSocketSubject 其本質(zhì)上是 ReplaySubject 的“重放”能力回梧。當(dāng)然你可以通過 webSocket 的第二個參數(shù)改變這種行為废岂。

多路復(fù)用

一般來說我們不太可能只會一個 Web Socket 服務(wù)完成所有的事,然而也不太可能針對每一個業(yè)務(wù)實例創(chuàng)建一個 webSocket狱意。往往我們會增加一層網(wǎng)關(guān)并將這些業(yè)務(wù) WebSocket 進行匯總湖苞,對于前端始終只需要一個連接,這就是多路復(fù)用存在的意義详囤。

而核心是必須要讓后端知道财骨,什么時候發(fā)送什么消息給什么樣的服務(wù)。

首先必須先使用 multiplex 方法來創(chuàng)建 Observable 以便訂閱某一路消息藏姐,它有三個參數(shù)來幫助我們區(qū)分消息:

  • subMsg 告知正在訂閱哪一路消息
  • unsubMsg 告知取消訂閱哪一路消息
  • messageFilter 過濾消息隆箩,使訂閱者只接收哪一路消息
const ws = webSocket('wss://echo.websocket.org');
const user$ = this.ws.multiplex(
    () => ({ type: 'subscribe', tag: 'user' }),
    () => ({ type: 'unsubscribe', tag: 'user' }),
    message => message.type === 'user'
);
user$.subscribe(message => console.log(message));

const todo$ = this.ws.multiplex(
    () => ({ type: 'subscribe', tag: 'todo' }),
    () => ({ type: 'unsubscribe', tag: 'todo' }),
    message => message.type === 'todo'
);
todo$.subscribe(message => console.log(message));

user$ 流和 todo$ 流他們共用一個 WebSocket 連接,這便是多路復(fù)用羔杨。

雖然訂閱是通過 multiplex 創(chuàng)建的捌臊,然后消息的推送依然還是需要使用 ws.next()

總結(jié)

這原本是對內(nèi)部一個簡單培訓(xùn)兜材,然而我發(fā)現(xiàn)竟然極少人會討論 RxJS 里面 Web Socket 的實現(xiàn)娃属。

其實一直有想著要給 ng-alain 內(nèi)置 WebSocket,只是就封裝角度來講完全沒有價值护姆,因為已經(jīng)足夠優(yōu)雅矾端。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市卵皂,隨后出現(xiàn)的幾起案子秩铆,更是在濱河造成了極大的恐慌,老刑警劉巖灯变,帶你破解...
    沈念sama閱讀 216,843評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件殴玛,死亡現(xiàn)場離奇詭異,居然都是意外死亡添祸,警方通過查閱死者的電腦和手機滚粟,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,538評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來刃泌,“玉大人凡壤,你說我怎么就攤上這事“姨妫” “怎么了亚侠?”我有些...
    開封第一講書人閱讀 163,187評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長俗扇。 經(jīng)常有香客問我硝烂,道長,這世上最難降的妖魔是什么铜幽? 我笑而不...
    開封第一講書人閱讀 58,264評論 1 292
  • 正文 為了忘掉前任滞谢,我火速辦了婚禮串稀,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘狮杨。我一直安慰自己母截,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,289評論 6 390
  • 文/花漫 我一把揭開白布禾酱。 她就那樣靜靜地躺著微酬,像睡著了一般。 火紅的嫁衣襯著肌膚如雪颤陶。 梳的紋絲不亂的頭發(fā)上颗管,一...
    開封第一講書人閱讀 51,231評論 1 299
  • 那天,我揣著相機與錄音滓走,去河邊找鬼垦江。 笑死,一個胖子當(dāng)著我的面吹牛搅方,可吹牛的內(nèi)容都是我干的比吭。 我是一名探鬼主播,決...
    沈念sama閱讀 40,116評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼姨涡,長吁一口氣:“原來是場噩夢啊……” “哼衩藤!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起涛漂,我...
    開封第一講書人閱讀 38,945評論 0 275
  • 序言:老撾萬榮一對情侶失蹤赏表,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后匈仗,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體瓢剿,經(jīng)...
    沈念sama閱讀 45,367評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,581評論 2 333
  • 正文 我和宋清朗相戀三年悠轩,在試婚紗的時候發(fā)現(xiàn)自己被綠了间狂。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,754評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡火架,死狀恐怖鉴象,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情距潘,我是刑警寧澤炼列,帶...
    沈念sama閱讀 35,458評論 5 344
  • 正文 年R本政府宣布,位于F島的核電站音比,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏氢惋。R本人自食惡果不足惜洞翩,卻給世界環(huán)境...
    茶點故事閱讀 41,068評論 3 327
  • 文/蒙蒙 一稽犁、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧骚亿,春花似錦已亥、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,692評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至覆醇,卻和暖如春妆够,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背迎膜。 一陣腳步聲響...
    開封第一講書人閱讀 32,842評論 1 269
  • 我被黑心中介騙來泰國打工泥技, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人磕仅。 一個月前我還...
    沈念sama閱讀 47,797評論 2 369
  • 正文 我出身青樓珊豹,卻偏偏與公主長得像,于是被迫代替她去往敵國和親榕订。 傳聞我的和親對象是個殘疾皇子店茶,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,654評論 2 354

推薦閱讀更多精彩內(nèi)容

  • 看到Observable和RxJS就感覺很親切,因為之前做Android開發(fā)的時候接觸過RxJava劫恒。Obs...
    tuacy閱讀 5,611評論 0 5
  • Spring Web MVC Spring Web MVC 是包含在 Spring 框架中的 Web 框架贩幻,建立于...
    Hsinwong閱讀 22,394評論 1 92
  • 今天在STM32F429固件庫里面學(xué)習(xí)了調(diào)用里面的固件和函數(shù)段直,總結(jié)如下: 1.在根目錄下新建一個工程文件夾mypr...
    盛展翊閱讀 188評論 0 0
  • 許久沒有好好的看一會兒書,寫一會兒字了溶诞。在為數(shù)不多的空閑時間里鸯檬,不要總是將自己一整天都放在看電視劇或電影里。 PS...
    苗條的小黑胖子閱讀 150評論 0 0
  • 1 南昌五月的天氣還不算炎熱螺垢,學(xué)生會主席提議喧务,應(yīng)該趁現(xiàn)在搞事情,但是校領(lǐng)導(dǎo)可是見過世面的枉圃,拍著自己寬松凸出的大肚皮...
    炸雞好吃會長胖閱讀 255評論 2 1