How to periodically check live connection using rxjs?
我使用rxjs处理websocket连接
1 2 | var socket = Rx.Observable.webSocket('wss://echo.websocket.org') socket.resultSelector = (e) => e.data |
我想定期(5s)发送
我尝试没有成功。 我承认我有点迷失了所有可用于处理超时,清除或限制的操作员。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | // periodically send a ping message const ping$ = Rx.Observable.interval(2000) .timeInterval() .do(() => socket.next('ping')) const pong$ = socket .filter(m => /^ping$/.test(`${m}`)) .mergeMap( ping$.throttle(2000).map(() => Observable.throw('pong timeout')) ) pong$.subscribe( (msg) => console.log(`end ${msg}`), (err) => console.log(`err ${err}`), () => console.log(`complete`) ) |
但不幸的是,没有ping发送。
我也尝试使用成功而无法实现。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | const ping$ = Rx.Observable.interval(2000) .timeInterval() .do(() => socket.next('ping')) const pong$ = socket .filter(m => /^ping$/.test(`${m}`)) const heartbeat$ = ping$ .debounceTime(5000) .mergeMap(() => Rx.Observable.timer(5000).takeUntil(pong$)) heartbeat$.subscribe( (msg) => console.log(`end ${msg}`), (err) => console.log(`err ${err}`), () => console.log(`complete`) ) |
任何帮助表示赞赏。
您可以使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | function sendMockPing() { // random 0 - 5s delay return Observable.of('pong').delay(Math.random() * 10000 / 2); } Observable.timer(0, 5000) .map(i => 'ping') .concatMap(val => { return Observable.race( Observable.of('timeout').delay(3000), sendMockPing() ); }) //.filter(response => response === 'timeout') // remove all successful responses .subscribe(val => console.log(val)); |
观看现场演示:https://jsbin.com/lavinah/6/edit?js,console
这随机模拟了采用
在heartbeat $函数下面返回一个可观察的对象,您可以连续收听
1)每5000毫秒的每次往返
要么
2)
即使发出了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | heartbeat$(pingInterval: number, pongTimeout: number) { let start = 0; const timer$ = timer(0, pingInterval).pipe(share()); const unsub = timer$.subscribe(() => { start = Date.now(); this.ws.next('ping'); }); const ping$ = this.ws$.pipe( switchMap(ws => ws.pipe( filter(m => /^ping$/.test(`${m}`)), map(() => Date.now() - start), ), ), share(), ); const dead$ = timer$.pipe( switchMap(() => of(-1).pipe( delay(pongTimeout), takeUntil(ping$), ), ), ); return merge(ping$, dead$).pipe(finalize(() => unsub.unsubscribe())); } heartbeat$(5000, 3000).subscribe( (latency) => console.log(latency) // 82 83 82 -1 101 82 -1 -1 333 ...etc ) |
我终于找到了基于
我最初的错误是使用ping $作为heartBeat $的输入,而我应该使用$ pong
1 2 3 4 | // define the pong$ const pong$ = socket .filter(m => /^ping$/.test(`${m}`)) .share() |
//使用share()因为pong $被使用了两次
1 2 3 4 5 6 7 8 9 10 11 12 | const heartbeat$ = pong$ .startWith('pong') // to bootstrap the stream .debounceTime(5000) // wait for 5s after the last received pong$ value .do(() => this.socket.next('ping')) // send a ping .mergeMap(() => Observable.timer(3000).takeUntil(pong$)) // we merge the current stream with another one that will // not produce value while a pong is received before the end of the // timer heartbeat$.subscribe( (msg) => console.log(`handle pong timeout`), ) |