应用程序在Angular 2中启动时如何运行服务


99

我创建了一个服务SocketService,基本上它会初始化套接字以让应用程序在端口上侦听。该服务还与某些组件进行交互。

// socket.service.ts

export class SocketService {
    constructor() {
        // Initializes the socket
    }
    ...
}

我知道SocketService的Constructor()中的代码仅在组件使用SocketService时才开始运行。

通常,app.ts中的代码如下所示:

// app.ts

import {SocketService} from './socket.service';
...
class App {
    constructor () {}
}
bootstrap(App, [SocketService]);

但是,我希望在应用启动时运行此服务。因此,我做了一个技巧,只需添加private _socketService: SocketServiceApp的Constructor()。所以现在代码看起来像这样:

// app.ts(新)

import {SocketService} from './socket.service';
...
class App {
    constructor (private _socketService: SocketService) {}
}
bootstrap(App, [SocketService]);

现在可以了。问题有时是SocketService的Constructor()中的代码运行,有时却没有。那么我应该如何正确地做呢?谢谢


Answers:


134

Stuart的答案指向正确的方向,但是在APP_INITIALIZER上查找信息并不容易。简短的版本是您可以使用它在运行任何其他应用程序代码之前运行初始化代码。我搜索了一会儿,在这里这里找到了解释,以防它们从网络上消失,我将对其进行总结。

APP_INITIALIZER以角度/核心定义。您可以像这样将其包含在app.module.ts中。

import { APP_INITIALIZER } from '@angular/core';

APP_INITIALIZER是一个OpaqueToken(或自Angular 4起为InjectionToken),它引用ApplicationInitStatus服务。ApplicationInitStatus是一个多提供程序。它支持多种依赖关系,您可以在提供商列表中多次使用它。这样使用。

@NgModule({
  providers: [
    DictionaryService,
    {
      provide: APP_INITIALIZER,
      useFactory: (ds: DictionaryService) => () => return ds.load(),
      deps: [DictionaryService],
      multi: true
    }]
})
export class AppModule { }

此提供程序声明告诉ApplicationInitStatus类运行DictionaryService.load()方法。load()返回一个承诺,并且ApplicationInitStatus阻止应用程序启动,直到承诺解决为止。这样定义load()函数。

load(): Promise<any> {
  return this.dataService.getDiscardReasons()
  .toPromise()
  .then(
    data => {
      this.dictionaries.set("DISCARD_REASONS",data);
    }
  )
}

设置为首先加载字典,应用程序的其他部分可以安全地依赖它。

编辑:请注意,无论load()方法花费多长时间,这都会为您的应用增加前期加载时间。如果要避免这种情况,可以在路线上使用解析器


谢谢您的帮助……非常有帮助
Gaurav Joshi

5
这应该是公认的答案。当前的代码仅将一行代码从构造函数移动到init方法。尽管确实应该使构造函数保持尽可能简单,但是仅凭这种思想并不能使其成为正确的解决方案。使用APP_INITIALIZER做。
JP 10 Berge,

我认为所选答案没有错,因为它可以解决OP的问题。但是,由于我在某些图书馆的发展中也遇到类似的问题,因此我提出另一个问题问题的答案非常合适。
马查多

最好的方法做
Renil巴布

58

SocketService而是将构造函数中的逻辑移至方法,然后在主组件的构造函数中调用该逻辑,或者ngOnInit

套接字服务

export class SocketService{
    init(){
        // Startup logic here
    }
}

应用程式

import {SocketService} from './socket.service';
...
class App {
    constructor (private _socketService: SocketService) {
        _socketService.init();
    }
}
bootstrap(App, [SocketService]);

1
我不明白在方法中执行逻辑而不是在构造函数中执行什么逻辑,您能解释一下吗,在方法中执行逻辑的优点是什么?
Pardeep Jain

1
一种更清洁的方法imho
inobrian '16

12
构造函数应尽可能简单(通常只有注入点),以防您需要使用ngOnInit钩子添加更多逻辑。
塞尔吉奥

1
团队没有想到的另一件事。我在Angular 4上工作的越多,我意识到Aurelia框架的构建是如此出色。只需添加装饰器,便可以立即使用所有这些可能性。那些家伙知道他们在做什么。
Joel Hernandez

1
@CodyBugstein这取决于您的用例。如果只是一劳永逸,则只需调用async方法。如果需要等待结果,则可以Promiseinit()方法中返回a ,然后根据需要进行链接。无论如何,可以做到,但可能会很困难,并且需要您自己确定细节。如果您需要进一步的帮助,您可以随时提出问题,并提供确切问题的详细信息,社区将很乐意为您提供帮助。
SnareChops 18-3-26的


1

尝试创建服务构造函数,然后在组件的ngOnInit()中调用它。

  • 服务模块

 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;
        });   
  }  
}       

希望这可以帮助。


1
@Hongbo希望该服务在应用启动时运行,而不是在使用该服务的特定组件中运行
Jarod Moser

这个非常简单的答案对我有用。我喜欢简单的答案。谢谢。
Aggie Jon
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.