Summary
I have an application on Angular. There are i have three components: root, child1 (tabs.component.ts) and child2 (io.component.ts). Also, i have a service that sends get and post requests to tomcat server.
In child1 i have a ngoninit, where i invoke service method get. Also i have ngoninit in child2. Ngoninit from child1 starts first. In child1 get request fetch data from server too slow and ngoninit from child2 starts before get.subscribe(data=>this.data=data)
.
So the problem is that ngoninit method from child2 uses this data
and as get request not returned data yet it fills with undefined
.
So, i have next sequence:
Tried
to use async
, await
, toPromise()
but it doesn't work, ngoninit from child2 in all cases loaded before get finished.
Some code
ngOnInit from child1
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);
}
}
ngOnInit from child2
here i've got an error: 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;
}
How to wait for get request before ngoninit from child2 will call variable name
from subsystem?
Update
thx for your answers. I've tried Resolve
, but have
as seen, resolve
called after get, though this.actr.data
, as i understand, must invoke resolve
. Confused.
new getSubsystems from terminal.service
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 { }
app.module
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 { }
What's wrong with this?