我正在尝试第一次使用Observable,对此感到非常困惑。那里有很多小例子,每个例子都有不同的地方。简而言之,这就是我想要做的事情: 我有一个设置组件,允许用户修改应用程序中使用的设置。使用本地存储来保存它们,并且我能够对其进行修改,保存,在启动时读取等。设置非常有效。 但是现在我希望能够实时知道这些设置何时更改,因此我可以根据新设置更改某些DOM(例如标题)。现在,我正在尝试从我的设置服务中实现一个可观察到的回溯到app.component(其中显示标题),以便可以在更改标题后立即进行更新。但是我什至无法正确理解你的语法。这是settings.service代码:
import { Input } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/of';
import { AppSettings } from '../shared/app-settings';
import { APPSETTINGS } from "../shared/defaultSettings";
import { Inject, Injectable } from '@angular/core';
import { LOCAL_STORAGE, StorageService } from 'angular-webstorage-service';
import { LogService } from 'src/app/services/app-log.service';
@Injectable()
export class AppSettingsService {
@Input()
defaultSettings = APPSETTINGS;
settings: Observable<AppSettings>;
newSettings: AppSettings;
constructor( private logger: LogService,
@Inject(LOCAL_STORAGE) private storage: StorageService) {
this.settings = this.storage.get('TRACS3_SETTINGS');
if ( this.settings === null ) {
this.storage.set('TRACS3_SETTINGS', this.defaultSettings);
this.settings = this.storage.get('TRACS3_SETTINGS');
}
}
public getSettings(): any {
//return this.storage.get('TRACS3_SETTINGS');
//return this.storage.get('TRACS3_SETTINGS').asObservable();
let settingsObservable = new Observable(observer => {
return this.storage.get('TRACS3_SETTINGS');
})
}
public saveSettings(settings: AppSettings): void{
this.newSettings = settings;
this.storage.set('TRACS3_SETTINGS', settings);
}
}
和组件:
import { Component, OnInit } from '@angular/core';
import { MatIconRegistry } from "@angular/material/icon";
import { DomSanitizer } from "@angular/platform-browser";
import { Inject } from '@angular/core';
import { Observable } from 'rxjs';
import { AdalService } from 'adal-angular4';
import { environment } from '../environments/environment';
import { AppSettings } from './shared/app-settings'
import { AppSettingsService } from './services/app-settings.service';
import { APPSETTINGS } from './shared/defaultSettings';
import { LogService } from 'src/app/services/app-log.service';
import {LOCAL_STORAGE, WebStorageService} from 'angular-webstorage-service';
import { Aircraft } from "./shared/aircraft";
import { Content } from '@angular/compiler/src/render3/r3_ast';
import {TitleService } from './services/title.service';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent implements OnInit{
className: string;
aircraft: Aircraft[];
isAuthenticated$: Observable<boolean>;
settings: AppSettings;
defaultSettings: AppSettings;
constructor(
private titleService: TitleService,
private appSettingsService: AppSettingsService,
private matIconRegistry: MatIconRegistry,
private domSanitizer: DomSanitizer,
private adalService: AdalService,
private logger: LogService,
private _wing: Observable<string>,
@Inject(LOCAL_STORAGE) private storage: WebStorageService
){
this.settings = this.appSettingsService.getSettings();
adalService.init(environment.config);
this.appSettingsService.getSettings().subscribe(newSettings => this.settings = newSettings);
}
ngOnInit(){
this.className = this.constructor.toString().match(/\w+/g)[1];
this.adalService.handleWindowCallback();
this.logger.debug(this.className, "adal userInfo: ", this.adalService.userInfo);
this.settings = this.appSettingsService.getSettings();
this.logger.log(this.className, "Settings at startup: ", this.settings);
if (this.settings.wing == null )
this.settings = this.defaultSettings;
_wing = this.settings.wing;
}
login() {
this.adalService.login();
}
logout() {
this.adalService.logOut();
}
get authenticated(): boolean {
return this.adalService.userInfo.authenticated;
}
}
整个项目都在GitHub上的https://github.com/cpeddie/TRACS3.git
有人有一个简单的例子说明如何使用可观察对象吗?
谢谢。...
答案 0 :(得分:0)
此代码应该有效:
@Injectable()
export class AppSettingsService {
// Use of BehavioirSubject. This is where you post values into
private _settings$: BehaviorSubject<AppSettings> = new BehaviorSubject(APPSETTINGS)
// Settings observer. This is where you read from outside
settings$: Observable<AppSettings> = this._settings$.asObservable()
constructor(private logger: LogService,
@Inject(LOCAL_STORAGE) private storage: StorageService) {
var settings = this.storage.get('TRACS3_SETTINGS');
if ( settings !== null ) {
this._settings$.post(settings);
} else {
this.storage.set('TRACS3_SETTINGS', APPSETTINGS);
}
}
public saveSettings(settings: AppSettings): void{
this._settings$.next(settings)
this.storage.set('TRACS3_SETTINGS', settings);
}
}
BehaviorSubject(_settings $)背后的想法是,您可以在其上发布值并观察其他可观察到的公共设置$的变化。
每次您通过post()修改BehaviorSubject上的值时,都会触发公开的可观察事件。
这样,您甚至不需要getSettings()方法,因为您在组件中订阅了settings $。
答案 1 :(得分:0)
代码的问题在于,在服务的GetSettings()
方法中,您要做构造了Observable,但您不返回了它。
public getSettings(): any {
//return this.storage.get('TRACS3_SETTINGS');
//return
this.storage.get('TRACS3_SETTINGS').asObservable();
let settingsObservable = new Observable(observer => {
return this.storage.get('TRACS3_SETTINGS');
})
}
添加
return settingsObservable;
因此,在您的组件构造函数中,您没有预订要在服务中创建的Observable 实例。
this.appSettingsService.getSettings().subscribe(newSettings => this.settings = newSettings);
可以通过许多不同的方式(从值,数组,事件等)创建Observable。底线是可观察到的两个方面:发布/发送/创建和订阅/接收/读取。
您已经使用subscribe()
方法在组件中找到了后者,该方法在所有可观察的 types 上都可用。但是,前者仅适用于其他可观察的特定类型,这些类型增加了更多功能。
您需要使用的是主题。这使您可以使用next()
方法向该主题发布(更改设置的)消息。然后,可观察者的订阅者将根据其主题类型和行为方式接收适当的消息。有关不同主题类型的列表,请参见:http://reactivex.io/documentation/subject.html