2017-10-18 92 views
0

我需要創建服務,其中包含服務從服務器獲取的設置。這些設置是在應用程序中廣泛使用,而不是隻在一個地方:Angular,RxJS:爲具有AsyncSubject源的Observable分配一個新值

@Injectable() 
export class SettingsService { 
    private apiResource = '/settings'; 
    private settingsSubject$: AsyncSubject<Settings> = new AsyncSubject(); 
    public settings$: Observable<Settings> = this.settingsSubject$.asObservable(); 

    constructor(private jsonApiService: JsonApiService) { 
    } 

    public init(): void { 
    this.get() 
     .subscribe(settings => { 
     this.settingsSubject$.next(settings); 
     this.settingsSubject$.complete(); 
     }); 
    } 

    public update(settings: Settings) { 
    return this.jsonApiService.post(`${this.apiResource}`, settings)   
    } 

    private get() { 
    return this.jsonApiService.get(`${this.apiResource}`); 
    } 
} 

我把加載數據init方法和CoreModule爲了調用它來獲得應用程序啓動數據:

export class CoreModule { 
    constructor(private settingsService: SettingsService) { 
    this.settingsService.init(); 
    } 

正如你所看到的,我使用AsyncSubject來強制所有用戶在請求完成時等待。

問題是如何調用update函數時調用一個新值? 我試過使用:

public update(settings: Settings) { 
    return this.jsonApiService.post(`${this.apiResource}`, settings) 
     .do(() => { 
     this.settings$ = Observable.of(settings); 
     });  
    } 

但沒有任何反應。而且,我認爲這不是一個正確的方法。

PS。使用的一個示例:

export class SettingsComponent implements OnInit { 
    public settings: Settings; 
    public settingsForm: FormGroup; 
    constructor(private settingsService: SettingsService, 
       private fb: FormBuilder) { 
    } 

    ngOnInit() { 
    this.settingsService.settings$ 
     .subscribe(data => { 

     this.settings = data; 
     this.settingsForm = this.fb.group({ 
      corValue: [this.settings.corValue], 
     }); 
     }); 
    } 
} 

<div *ngIf="settings"> 
    <form [formGroup]="settingsForm"> 
    ... 
    </form> 
</div> 

另一個用途是服務:

@Injectable() 
export class CalculationService { 
    private corValue: number; 
    constructor(private settingsService: SettingsService) { 
    this.settingsService.settings$ 
     .subscribe(settings => { 
     this.corValue = settings.corValue; 
     }) 
    } 
... different functions that make some math calculations and some functions use corValue. 
} 

PS2。我無法使用APP_INITIALIZER,因爲我的設置是用戶特定的,所以用戶必須先登錄。

+0

你不能。 「AsyncSubject」存在,以便所有當前和未來的訂戶從AsyncSubject訂閱的源接收** last **值。主題通常用於連接觀察者;您明確地向主題提供了值,但效果是相同的:訂戶收到最後一個值。如果這不是你想要的行爲,那麼一個普通的'Subject'可能就是你應該使用的。此外,完成一個可觀察的信號給用戶,有**沒有進一步的價值**,實際上,用戶將自動取消訂閱。 – cartant

+0

@cartant'主題'是我第一次嘗試。我在問題中加入了一些代碼。在那裏你可以看到我訂閱了'settings $'並注意模板中的'ngIf'。所以,當我使用'Subject'時,有時候我沒有看到表單,有時會顯示,我認爲這是因爲請求沒有完成或其他。使用'AsyncSubject'我沒有這樣的問題。 – user348173

回答

0

如果我理解正確的話,你要改爲值發送到settingsSubject$settings$您的用戶收到這些下游:

public update(settings: Settings) { 
    return this.jsonApiService.post(`${this.apiResource}`, settings) 
    .do(() => { 
     this.settingsSubject$.next(settings); 
    });  
} 
+0

你理解正確......但它不起作用...因爲'settingsSubject $'已經完成(並且它必須在請求完成時完成)並且next的下一次調用不起任何作用。閱讀關於'AsyncSubject'的內容,你將會得到我的意思 – user348173

+0

@ user348173你是否希望訂閱者在Next處理器上運行,即使在「初始」完成之後? – concat

+0

@是的,不,我不想在完成後不能使用'next',所以我正在尋找某種方式向訂閱者說我有一些新的價值。 – user348173

相關問題