为什么我的@Injectable服务创建了多次?

时间:2019-08-28 09:17:50

标签: angular typescript

  

注意:由于该问题归结为一次@Injectable服务的反复说明,因此请向下滚动至“更新”。

我有一个可以为企业服务的解析器:

resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<any> | Promise<any> | any {
  this._logger.debug('Loading application data.');
  return forkJoin([
    this._userService.getMe(),
    this._businessService.getAll()
  ]).pipe(
    tap(([user, businesses]) => {
      this._appState.user = user;
      this._appState.businesses = businesses;
    }),
    finalize(() => this._logger.debug('Application data loaded.'))
  );
}

有一个ApplicationState,有两个BehaviorSubject成员_business_businesses

constructor() {
  this.businessChange = this._business.asObservable();
  this.businessesChange = this._businesses.asObservable();
}

set business(business: BusinessModel) {
  console.log(business);
  this._business.next(business);
}

get business(): BusinessModel {
  return this._business.getValue();
}

set businesses(value) {
  this._businesses.next(value);
  console.log(this.businesses);
}

get businesses(): Array<BusinessModel> {
  return this._businesses.getValue();
}

如您所见,在解析器中设置了businesses所述状态。 business取决于路由,并根据该路由设置在(延迟加载)模块中:

ngOnInit() {

  this._appState.businessesChange.subscribe(
    (b) => {
      console.log('businessesChange');
      console.log(b);
    }
  );

  this._subscriptions.add(
    this._activatedRoute.params
      .subscribe((params) => {
        this._routeParams = params;
        const businessId: number = parseInt(params['businessId'], 10);
        const businesses = this._appState.businesses;
        console.log(`businessId ${businessId}`);
        console.log('available businesses');
        console.log(businesses);
        this._appState.business = businesses.find(b => b.id === businessId);
      })
  );
}

这是相关的日志输出:

2019-08-28T09:11:04.989Z DEBUG [..~df7ced28.js:428] Loading application data.
ngx-logger.js:251 2019-08-28T09:11:04.992Z DEBUG [main.js:398] Fetching /me
application.state.ts:56 Set businesses:
application.state.ts:58 (3) [{…}, {…}, {…}]
ngx-logger.js:251 2019-08-28T09:11:06.781Z DEBUG Application data loaded.
businesses.component.ts:43 businessesChange
businesses.component.ts:44 []
businesses.component.ts:47 businessId 4
businesses.component.ts:48 available businesses
businesses.component.ts:49 []
application.state.ts:46 Set business:
application.state.ts:47 undefined
ngx-logger.js:251 2019-08-28T09:11:08.386Z DEBUG Place is null. No action.

如您所见,businesses被设置并包含三个元素。然后,我们从解析器看到应用程序数据已加载。。之后,我们看到_activatedRoute.params订阅声明该路由显示businessId的{​​{1}},但是随后。4突然是一个空列表-初始值this._appState.businesses的内容,即使我们稍早打印了该内容。

由于我也正在登录/调试BehaviorSubject方法,因此我可以看到在将该值设置为三个元素的列表后,不会被更改。

我不知道这是怎么回事。可能是什么原因造成的?


我已经尝试过的:

  • 重新启动服务器
  • 使用调试器(但我还是要进行printf-debug调试)

更新

好吧,我将问题归结为set被多次宣告:

通过为ApplicationState提供一个简单的ID(时间戳):

ApplicationState

并在constructor() { this.businessChange = this._business.asObservable(); this.businessesChange = this._businesses.asObservable(); this.timestamp = moment().format('MM.SS SSS'); console.log(`${this.timestamp} ApplicationState created`); } set方法中更改日志输出,我得到了:

get

因此,08.09 095 ApplicationState created ngx-logger.js:251 2019-08-28T09:51:16.098Z DEBUG Loading application data. ngx-logger.js:251 2019-08-28T09:51:16.099Z DEBUG [main.js:398] Fetching /me :4200/#/businesses/4/calendar:1 This site does not have a valid SSL certificate! Without SSL, your site's and visitors' data is vulnerable to theft and tampering. Get a valid SSL certificate before releasing your website to the public. application.state.ts:60 08.09 095 Set businesses: application.state.ts:62 (3) [{…}, {…}, {…}] application.state.ts:38 08.14 145 ApplicationState created ngx-logger.js:251 2019-08-28T09:51:16.161Z DEBUG Application data loaded. businesses.component.ts:43 businessesChange businesses.component.ts:44 [] businesses.component.ts:54 businessId 4 businesses.component.ts:55 available businesses businesses.component.ts:56 [] application.state.ts:50 08.14 145 Set business: application.state.ts:51 undefined ngx-logger.js:251 2019-08-28T09:51:16.178Z DEBUG Place is null. No action. calendar.component.ts:105 有一个08.09 095(A)和一个08.14 145(B)实例。

A设定了业务,但显然使用了B。

我检查过,ApplicationState在我的ApplicationState中仅被导入一次:

ApplicationModule

那为什么会这样呢?这不是辛格尔顿吗?是因为这经过了延迟加载的模块吗?

但最重要的是:为什么在过去的几周中一直如此?

我现在还添加了providers: [ // Services ApplicationState, ApiServices, ApplicationResolver, ]

providedIn

但它的行为仍然相同。

1 个答案:

答案 0 :(得分:0)

好吧,发生这种情况的答案为什么显然是由于延迟加载。似乎有一些事情要做依赖树的构建或类似的事情。

我不知道详细信息,我将接受任何有关此主题的更详细的分析器。

无论如何,我认为在 parent 模块中提供服务就足够了。因为有了感觉,不是吗?

事实证明,这确实必须在app.module.ts中提供。我在提供application.module.ts的地方有另一个名为ApplicationState的模块(不应混淆)。 application.module.ts是延迟加载的,但也有一些路由再次被延迟加载,例如businesses.module.ts。所以我的层次结构看起来像这样:

app.module.ts
|_ application.module.ts  // lazy, providers: [ApplicationState]
|  |_ businesses.ts       // lazy, uses ApplicationState too
|_ public-pages.module.ts // not lazy

我需要更改的是设置

providers: [ApplicationState]
app.module.ts

这不是理想的imo,但是由于延迟加载是这样工作的,因此我将不得不对其进行处理。

显然这是一个已知问题(https://github.com/angular/angular/issues/12869),但是堆栈上也有可能的解决方案溢出https://stackoverflow.com/a/41293784/826983