Reputation: 49996
I created a service SocketService, basically it initializes the socket to let the app listen on the port. This service also interacts with some components.
// socket.service.ts
export class SocketService {
constructor() {
// Initializes the socket
}
...
}
I know the code in SocketService's constructor() only starts to run when a component use SocketService.
And usually the code in app.ts looks like this:
// app.ts
import {SocketService} from './socket.service';
...
class App {
constructor () {}
}
bootstrap(App, [SocketService]);
However, I want this service run when the app starts. So I made a trick, just add private _socketService: SocketService
in App's constructor(). Now the code looks like this:
// app.ts (new)
import {SocketService} from './socket.service';
...
class App {
constructor (private _socketService: SocketService) {}
}
bootstrap(App, [SocketService]);
Now it works. The problem is sometimes the code in SocketService's constructor() runs, and sometimes not. So how should I do it correctly?
Upvotes: 135
Views: 115539
Reputation: 6179
socket.service.ts
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root',
})
export class SocketService {
init() {
console.log("socket service initialized");
}
}
app.component.ts
import { Component } from '@angular/core';
import {SocketService} from './socket.service';
@Component({
selector: 'app-root',
templateUrl: 'app.component.html',
styleUrls: ['app.component.scss'],
})
export class AppComponent {
constructor(private _socketService: SocketService) {
this._startupService.init();
}
}
Upvotes: 1
Reputation: 1
in config.teml.json
{Domain:'your url'}
in app.module.ts
import * as mydata from '../assets/config.teml.json';
const data:any=(mydata as any).default;
let config: SocketIoConfig = { url: data.Domain, options: { } };
Upvotes: 0
Reputation: 2950
Stuart's answer points in the right direction, but it's not easy to find information on APP_INITIALIZER. The short version is you can use it to run initialization code before any of your other application code runs. I searched for a while and found explanations here and here, which I will summarize in case they disappear from the web.
APP_INITIALIZER is defined in angular/core. You include it in your app.module.ts like this.
import { APP_INITIALIZER } from '@angular/core';
APP_INITIALIZER is an OpaqueToken (or an InjectionToken since Angular 4) that references the ApplicationInitStatus service. ApplicationInitStatus is a multi provider. It supports multiple dependencies and you can use it in your providers list multiple times. It is used like this.
@NgModule({
providers: [
DictionaryService,
{
provide: APP_INITIALIZER,
useFactory: (ds: DictionaryService) => () => return ds.load(),
deps: [DictionaryService],
multi: true
}]
})
export class AppModule { }
This provider declaration tells the ApplicationInitStatus class to run the DictionaryService.load() method. load() returns a promise and ApplicationInitStatus blocks the app startup until the promise resolves. The load() function is defined like this.
load(): Promise<any> {
return this.dataService.getDiscardReasons()
.toPromise()
.then(
data => {
this.dictionaries.set("DISCARD_REASONS",data);
}
)
}
Set up like that the dictionary gets loaded first and the other parts of the app can safely depend on it.
Edit: Be aware that this will increase the up-front load time for you app by however long the load() method takes. If you want to avoid that you could use a resolver on your route instead.
Upvotes: 174
Reputation: 8963
Also see APP_INITIALIZER, which is described as;
A function that will be executed when an application is initialized.
Upvotes: 11
Reputation: 13805
Try Creating service constructor & then call it in ngOnInit() of your component.
export class SocketService {
constructor() { }
getData() {
//your code Logic
}
}
export class AppComponent {
public record;
constructor(private SocketService: DataService){ }
ngOnInit() {
this.SocketService.getData()
.subscribe((data:any[]) => {
this.record = data;
});
}
}
Hope this Helps.
Upvotes: 0
Reputation: 13347
Move the logic in your SocketService
constructor to a method instead and then call that in your main component's constructor or ngOnInit
SocketService
export class SocketService{
init(){
// Startup logic here
}
}
App
import {SocketService} from './socket.service';
...
class App {
constructor (private _socketService: SocketService) {
_socketService.init();
}
}
bootstrap(App, [SocketService]);
Upvotes: 62