2017-10-18 89 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

相关问题