6

在这方面非常感谢您的帮助。

这是我想要做的,当我访问主应用程序页面时,它从 config.service.ts 调用 getConfigs() 并从后端获取数据,然后更新 this.configStringSource.next(config)。在那之后,我试图将其重定向到 this.router.navigate(['/clone/status']),但没有发生重定向。

app.routing.ts

import { Routes, RouterModule } from '@angular/router';

import { CloneComponent } from './clone/clone.component';
import { StatusComponent } from './status/status.component';
import { ConfigurationComponent } from './configuration/configuration.component';
import { LogsComponent } from './logs/logs.component';
import { ConfigResolver } from './_services/config-resolver.service';

const appRoutes: Routes = [
    { path: 'clone', component: CloneComponent, children: [
        {path: 'status', component: StatusComponent, resolve: {config: ConfigResolver} },
        ]
    },
    { path: 'logstream', component: LogstreamComponent },
];

export const AppRouting = RouterModule.forRoot(appRoutes);

配置文件

export class Config {
    configID: string;
    sourceDbNodes: string;
    targetDbNodes: string;
}

配置服务.ts

import { Injectable, OnInit } from '@angular/core';
import { Http, Headers, Response } from '@angular/http';
//import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map';
import { Router } from '@angular/router';
import {Subject} from 'rxjs/Subject';

import { Config } from '../_models/config';

@Injectable()
export class ConfigService {

    // Observable string source
    private configsStringSource = new BehaviorSubject<Config>({ configID: "", sourceDbNodes: "", targetDbNodes: ""});

    // Observable string stream
    configsString$ = this.configsStringSource.asObservable();

    // Service message commands
    updateConfigs(configs: Config) {
      this.configsStringSource.next(configs)
    }

    constructor(private http: Http, private router:Router) { }

    getConfigs() {
      let headers = new Headers();
      headers.append('Content-Type','application/json');
      return this.http.get('http://localhost:8080/sample1/api/config', { headers: headers })
        .map((response: Response) => response.json());
    }
}

配置解析器.service.ts

import { Resolve, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
import { Observable } from 'rxjs/Observable';
import { Injectable } from '@angular/core';

import { ConfigService } from './config.service';
import { Config } from '../_models/config';

interface Server {
  id: number;
  name: string;
  status: string;
}

@Injectable()
export class ConfigResolver implements Resolve<Config> {

  config: Config;

  constructor(private configService: ConfigService) {}

  resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<Config> | Promise<Config> | Config {
    return this.configService.configsString$.map(
      data => data[1]);
    }
}

app.component.ts

import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';

import { Config } from './_models/config';
import { ConfigService } from './_services/config.service';

@Component({
  moduleId: module.id.toString(),
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})

export class AppComponent implements OnInit {
  configs: Config[];

  constructor(private router:Router, private configService:ConfigService ) { }

  title = 'Angular 4 Proeject';

  private getConfigs() {
    this.configService.getConfigs().subscribe(configs => { 
        this.configs = configs;
                this.configService.updateConfigs(configs);
console.log('app.component.ts sourceDbNode = '+this.configs[0].sourceDbNodes);
    });
  }

  ngOnInit() {
    this.getConfigs();
    this.router.navigate(['/clone/status']);
  }

}

status.component.ts

import { Component, Input, OnInit, AfterContentChecked } from '@angular/core';
import { ActivatedRoute, Params, Router, Data } from '@angular/router';

import { Config } from '../_models/config';
import { ConfigService } from '../_services/config.service';

@Component({
  selector: 'app-status',
  template: `
    <p>
      status Works! {{config}}
    </p>
  `,
  styleUrls: ['./status.component.scss']
})

export class StatusComponent implements OnInit {

  configs: string;
  config: Config;
  servers: Array<any>;
  server: { id: number; name: string; status: string; };

  constructor(private configService:ConfigService,
              private route: ActivatedRoute,
              private router: Router) { }

  ngOnInit() {
    this.route.data.subscribe(
        (data: Data) => {
          this.config = data['config'];
console.log('status.component.ts data = ', data['config']);
console.log('status.component.ts this.config = ', this.config);
        }
    );
  }
}
4

2 回答 2

13

您的问题是已解决的 observables 需要完成,因此您只需将 .take(1) 或 .first() 添加到您的解析器 observable 中,例如:

resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<Config> | Promise<Config> | Config {
    return this.configService.configsString$.map(
      data => data[1]).take(1);
}

但是,有一种更简洁的方式来加载配置服务:

import { Injectable, APP_INITIALIZER } from '@angular/core';
import { Config } from './_models/config';

@Injectable()
export class ConfigService {
  protected config: Config;

  constructor(private http: Http) {
  }

  getConfigs(): Observable<any> {
    let headers = new Headers();
    headers.append('Content-Type','application/json');
    return this.http.get('http://localhost:8080/sample1/api/config', { headers: headers })
               .map((response: Response) => response.json());
  }

  public load() {
     return new Promise((resolve, reject) => {
       this.getConfigs()
         .subscribe(
           config => {
             this.config = config;
             resolve(true);
           },
           err => resolve(err)
         );
     });
  }
}

export function ConfigServiceInitFactory(configService: ConfigService) {
  return () => configService.load();
}

export const ConfigServiceInitProvider = {
  provide: APP_INITIALIZER,
  useFactory: ConfigServiceInitFactory,
  deps: [ConfigService],
  multi: true
}

然后在您的应用程序模块中,导入 ConfigService 和 ConfigServiceInitProvider 并像这样提供它们:

providers: [
  ConfigService,
  ConfigServiceInitProvider,
  ... remaining service providers..
]

这将确保您的配置在几乎任何其他内容之前加载,并且您可以在任何需要的地方注入您的配置服务,并且配置将始终以同步方式可用。

于 2017-11-15T13:58:27.750 回答
1

它对我有帮助。在config.service更改

// Observable string stream
configsString$ = this.configsStringSource.asObservable();

堆叠。_

将 .first()添加到.asObservable ()

于 2017-11-15T13:36:24.153 回答