javascript - 在ngoninit开始之前等待http get请求完成
问题描述
概括
我在 Angular 上有一个应用程序。我有三个组件:root、 child1 ( tabs.component.ts ) 和child2 ( io.component.ts )。另外,我有一个服务可以向 tomcat 服务器发送 get 和 post 请求。
在child1 中,我有一个ngoninit,我在其中调用服务方法 get。我在child2也有 ngoninit 。child1 的 Ngoninit首先启动。在child1获取请求从服务器获取数据太慢并且来自 child2 的 ngoninit开始之前get.subscribe(data=>this.data=data)
。
所以问题是来自 child2 的 ngoninit 方法使用它data
,并且作为 get 请求未返回数据但它填充undefined
. 所以,我有下一个序列:
试过了
使用async
, await
,toPromise()
但它不起作用,来自 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);
}
}
终端服务.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
?
更新
谢谢你的回答。我试过Resolve
了,但是有
如所见,resolve
在 get 之后调用,但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;}));
}
孩子1
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);
}
}
解决服务
export class ResolverService implements Resolve<any>{
constructor(private terminalService: TerminalService) { }
resolve(){
console.log('resolve');
return this.terminalService.getSubsystems();
}
}
解析模块
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 { }
这有什么问题?
解决方案
我用它解决了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()
函数以加载获取请求
应用程序.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();
}
}
推荐阅读
- python - 如何在 Gurobi 问题中使用复变量
- mapbox-gl-js - 在地图中组合多个样式
- amazon-web-services - AWS - 无需订阅即可发送短信
- neo4j - Neo4J Cypher - 在循环处理后设置一次数据
- kotlin - 无法通过匹配组替换文本:ArrayIndexOutOfBoundsException: length=2; 指数=2
- .htaccess - 使用 .htaccess 更改 404 错误:自定义 404 错误页面
- r - R:在特定字符位置拆分蛋白质组学数据的数据框列
- apache-spark - 如何将 Hive 表中的所有时间戳转换为 EST
- angular - 如何在 tab-header-pagination 中触发下一个或上一个箭头单击的功能?我想在每个箭头单击时加载下一个或上一个 3 个选项卡
- apache-flink - Flink Logger nullPointException