2017-08-04 97 views
1

使用RxJS和Angular 2處理服務器重新連接的最佳方式是什麼?使用RxJS和角度2 HTTP服務重新連接服務器

這是我到目前爲止有:在控制檯

import { Injectable } from '@angular/core'; 
import { Http, Response } from '@angular/http'; 

import { Observable } from 'rxjs/Observable'; 
import { BehaviorSubject } from 'rxjs/BehaviorSubject'; 
import 'rxjs/add/operator/takeUntil'; 
import 'rxjs/add/observable/throw'; 

@Injectable() 
export class ConnectionService { 

    // Stores the current status of the connection, false = not connected 
    serviceOnline: BehaviorSubject<boolean> = new BehaviorSubject(false) 

    constructor(
    private http: Http 
) { 
    this.serviceOnline.asObservable().subscribe((online) => { 
     console.log("Service online: " + JSON.stringify(online)) 
    }) 
    setTimeout(() => this.setServiceOffline(), 2000); 
    } 

    setServiceOffline() { 
    console.log("Setting service offline"); 
    this.serviceOnline.next(false); 
    this.testConnection().delay(2000).repeat().takeUntil(this.serviceOnline).subscribe(); 
    } 

    testConnection(): Observable<boolean> { 
    console.log("Testing connection"); 
    return new Observable(observer => { 
     this.http.get(`http://endpoint/ping`) 
     .timeout(5000) 
     .catch((error: any) => Observable.throw(error)) 
     .subscribe(() => { 
      console.log("Connection successful"); 
      if(this.serviceOnline.getValue() == false) 
      this.serviceOnline.next(true); 
      observer.next(true); 
      observer.complete(); 
     }, (error) => { 
      console.log("Connection failed"); 
      if(this.serviceOnline.getValue() == true) 
      this.serviceOnline.next(false); 
      observer.next(false); 
      observer.complete(); 
     }); 
    }) 
    } 
} 

結果:

Service online: false 
Setting service offline 
Service online: false 
Testing connection 
Connection failed 

如果我替換此行..

this.testConnection().delay(2000).repeat().takeUntil(this.serviceOnline).subscribe(); 

this.testConnection().delay(2000).repeat().take(5).subscribe(); 

我得到了重複:

Service online: false 
Setting service offline 
Service online: false 
Testing connection 
Connection failed 
Connection failed 
Connection failed 
Connection failed 
Connection failed 

documentation

公共takeUntil(通知:可觀察):可觀察

發射被源可觀察到發射的值通知器 Observable發出一個值。

serviceOnline BehaviorSubject只在服務器狀態發生更改時更新。這條線後...

this.serviceOnline.next(false); 

... serviceOnline只有當發出HTTP服務返回的成功響應另一個值,如果當前的在線狀態爲假(斷開):

if(this.serviceOnline.getValue() == false) 
    this.serviceOnline.next(true); 

所以takeUntil應該工作。我在這裏誤解/錯過了什麼?

我是新來RxJS - 改善這個代碼執行任何其他指針也將不勝感激...

這裏是一個Plnkr:http://plnkr.co/edit/WUKxH6nFxc8LMKcxDPql?p=info

RxJS 5.4版本。角版本4


返回serviceOnline作爲觀察到不解決這個問題:。 this.testConnection()延遲(2000).repeat()takeUntil(this.serviceOnline.asObservable())進行訂閱。 ();

回答

0

我覺得出現問題的時候訂閱,因爲它是BehaviorSubject一個實例,因爲this.serviceOnline總是發出的最後一個值。當您通過takeUntil運算符作爲通知符observable時,takeUntil會訂閱它,並立即收到導致即時完成結果可觀察項的通知。請注意,這不要緊,無論在通知發出觀察到或truefalsetakeUntil每當收到任何值完成。

嘗試.takeUntil(this.serviceOnline.filter(online => online === true))代替。

+0

賓果!修好了 - 謝謝! – lufin

0

嗯你有沒有嘗試過這樣做?:

this.testConnection().delay(2000).repeat().takeUntil(this.serviceOnline.asObservable()).subscribe(); 
+0

是啊,我也試過了。我會在這個問題上加上這一點。謝謝 – lufin

+0

嗯所以,我建議你嘗試調試你的serviceOnline,如下所示: 'constructor(private http:Http){this.serviceOnline.asObservable()。subscribe(notification => { console.log(notification ) }) }' –

+0

是的,我也想知道,如果serviceOnline立即發射的值並導致takeUntil重複testConnection觀察到前火,但事實並非如此。 'this.serviceOnline.next(false)'調用之後會發出一個錯誤值,除非發出成功的http請求,否則不會再次發生。在這種情況下,它應該重複一遍,就像使用Take(它給出有限的重複)一樣。怪怪的? – lufin