使用可观察的角度传达变量变化

时间:2019-03-02 17:20:04

标签: angular rxjs

我正在尝试第一次使用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

有人有一个简单的例子说明如何使用可观察对象吗?

谢谢。...

2 个答案:

答案 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);

RxJS机制

可以通过许多不同的方式(从值,数组,事件等)创建Observable。底线是可观察到的两个方面:发布/发送/创建和订阅/接收/读取。

您已经使用subscribe()方法在组件中找到了后者,该方法在所有可观察的 types 上都可用。但是,前者仅适用于其他可观察的特定类型,这些类型增加了更多功能。

您需要使用的是主题。这使您可以使用next()方法向该主题发布(更改设置的)消息。然后,可观察者的订阅者将根据其主题类型和行为方式接收适当的消息。有关不同主题类型的列表,请参见:http://reactivex.io/documentation/subject.html