在ngoninit启动angular之前,等待http get请求完成

时间:2019-11-08 02:13:38

标签: javascript angular typescript

摘要

我在Angular上有一个应用程序。我有三个组件: root child1 (tabs.component.ts)和 child2 (io.component.ts)。另外,我有一项将get和post请求发送到tomcat服务器的服务。

child1 中,我有一个ngoninit,在其中我调用服务方法get。我在 child2 中也有ngoninit。 child1 中的Ngoninit首先启动。在 child1 中,从服务器获取数据的请求太慢,并且 child2 的ngoninit在get.subscribe(data=>this.data=data)之前开始。

所以问题在于 child2 的ngoninit方法使用了此data,并且由于get请求未返回数据,但它仍填充了undefined。 所以,我有下一个序列:

sequence (console)

尝试

要使用asyncawaittoPromise(),但是它不起作用,在完成加载的所有情况下, child2 中的ngoninit都会被加载。

某些代码

child1的ngOnInit

subsystems: Subsystem[]; //need to ngFor them on html
currentTabId;

constructor(private terminalService: TerminalService) {}

ngOnInit() {
try {
  console.log('child1 ngoninit');
  this.terminalService.getSubsystems().subscribe((data: []) => {
    console.log('get in child1 finished');
    this.subsystems=data;
    this.currentTabId=0;
    this.terminalService.setSubsystem(this.subsystems[this.currentTabId]);
  });
} catch (exception) {
  console.log(exception);
}
}

child2的ngOnInit

这里我有一个错误:TypeError: Cannot read property 'name' of undefined

constructor(private terminalService: TerminalService) {}

ngOnInit() {
try {
  console.log('child2 ngoninit');
  this.terminalService
    .getResultsBySubsystem(this.terminalService.getSubsystem().name) //here
    .subscribe((data: Command[])=> {
      console.log(data);
      data.forEach((value)=> {
        this.terminalService.setCurrentResult(value.getCommand+'\n'+value.getResult+'\n');
      });
    });
}
catch (exception) {
  console.log(exception);
  this.terminalService.addCurrentResult(this.CONNECTION_ERROR_MSG);
}
}

terminal.service.ts

subsystem: Subsystem;

constructor(private httpClient: HttpClient) {}

getSubsystems() {
  return this.httpClient.get('http://localhost:8080/subsystems');
}

getResultsBySubsystem(name: string) {
  return this.httpClient.get('http://localhost:8080/subsystems/'+name+'/result');
}

getSubsystem() {
  console.log('getSubsystem terminal.service invoking');
  return this.subsystem;
}

setSubsystem(subsystem: Subsystem) {
  console.log('setSubsystem terminal.service invoking ');
  this.subsystem=subsystem;
}

child2 的ngoninit从子系统调用变量name之前,如何等待获取请求?

更新

thx为您的答案。我已经尝试过Resolve,但是有

newConsole

如图所示,resolve在获取后调用,尽管据我所知this.actr.data必须调用resolve。困惑。

terminal.service的新getSubsystems

import {map} from 'rxjs/operators';


subsystem: Subsystem;

constructor(private httpClient: HttpClient) {}

getSubsystems() {
    console.log('getSubsystems in terminal.service invoking');
    return this.httpClient.get<Subsystem[]>('http://localhost:8080/subsystems')
      .pipe(map(value=>{console.log(value); return value;}));
  }

child1

subsystems: Subsystem[];
currentTabId;

constructor(private terminalService: TerminalService, private actr: ActivatedRoute) {}

ngOnInit() {
    console.log('child1 ngoninit');
    try {
      this.terminalService.setCurrentResult('Connecting...');
      this.actr.data.subscribe((data: []) => { //this
        console.log('get in child1 finished');
        this.subsystems=data;
        console.log(data);
        this.currentTabId=0;
        this.terminalService.setSubsystem(this.subsystems[this.currentTabId]);
      });
    } catch (exception) {
      console.log(exception);
    }
  }

resolve.service

export class ResolverService implements Resolve<any>{

  constructor(private terminalService: TerminalService) { }

  resolve(){
    console.log('resolve');
    return this.terminalService.getSubsystems();
  }
}

resolve.module

import {RouterModule, Routes} from '@angular/router';
import {ResolverService} from './services/resolver.service';

const routes: Routes = [
  {
    path: '',
    component: AppComponent,
    resolve: {
      subsystems: ResolverService
    }
  }
];

export const routing = RouterModule.forRoot(routes);

@NgModule({
  declarations: [],
  imports: [CommonModule],
  exports: [RouterModule],
  providers: [ResolverService]
})
export class ResolverModule { }

应用模块

import {ResolverModule} from './resolver.module';
import { routing } from './resolver.module';
import {RouterModule} from '@angular/router';

@NgModule({
  declarations: [
    AppComponent,
    TabsComponent,
    IoComponent
  ],
  imports: [
    BrowserModule,
    FormsModule,
    BrowserAnimationsModule,
    HttpClientModule,
    routing
  ],
  exports: [RouterModule],
  providers: [ResolverModule],
  bootstrap: [AppComponent]
})
export class AppModule { }

这怎么了?

1 个答案:

答案 0 :(得分:0)

我用APP_INITIALIZER

解决了

app.module.ts

import { BrowserModule } from '@angular/platform-browser';
import {APP_INITIALIZER, NgModule} from '@angular/core';
import { AppComponent } from './app.component';
import {FormsModule} from '@angular/forms';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { TabsComponent } from './tabs/tabs.component';
import {HttpClientModule} from '@angular/common/http';
import { IoComponent } from './io/io.component';
import {AppConfig} from './config/app.config';

export function loadConfig(config: AppConfig) {
  return () => config.load();
}

@NgModule({
  declarations: [
    AppComponent,
    TabsComponent,
    IoComponent
  ],
  imports: [
    BrowserModule,
    FormsModule,
    BrowserAnimationsModule,
    HttpClientModule,
  ],
  bootstrap: [AppComponent],
  providers: [
    AppConfig,
    {provide: APP_INITIALIZER, useFactory: loadConfig, deps: [AppConfig], multi: true}
  ]
})
export class AppModule {
}

创建配置文件和load()函数以在加载组件的构造函数之前加载get请求

app.config.ts

import {Injectable} from '@angular/core';
import {HttpClient} from '@angular/common/http';
import {Subsystem} from '../data/subsystem';
import {map} from 'rxjs/operators';

@Injectable()
export class AppConfig {

  private subsystems: Subsystem[] = null;
  private subsystem: Subsystem = null;

  constructor(private http: HttpClient) {

  }

  load() {
    return new Promise((resolve) => {
      this.http
        .get('http://localhost:8080/subsystems')
        .pipe(map(value=>value))
        .subscribe((data: Subsystem[]) => {
          this.subsystems = data;
          resolve(true);
        });
    });
  }

  public getSubsystem() {
    return this.subsystem;
  }

  public setSubsystem(subsystem: Subsystem) {
    this.subsystem=subsystem;
  }

  public getSubsystems() {
    return this.subsystems;
  }

  public setSubsystems(subsystems: Subsystem[]) {
    this.subsystems=subsystems;
  }
}

使用初始化数据

tabs.component.ts

import {Component, OnInit} from '@angular/core';
import {Subsystem} from '../data/subsystem';
import {AppConfig} from '../config/app.config';

@Component({
  selector: 'app-tabs-component',
  templateUrl: 'tabs.component.html',
  styleUrls: ['./tabs.component.css'],
})

export class TabsComponent implements OnInit {

  subsystems: Subsystem[];
  subsystem: Subsystem;
  currentTabId;

  constructor(private config: AppConfig) {
  }

  ngOnInit() {
    this.currentTabId=0;
    this.subsystems=this.config.getSubsystems();
    this.config.setSubsystem(this.subsystems[this.currentTabId]);
    this.subsystem=this.config.getSubsystem();
  }

  tabPressed(id) {
    this.currentTabId=id;
    this.config.setSubsystem(this.subsystems[id]);
    this.subsystem=this.config.getSubsystem();
  }

}