Angular 7日志记录服务对象参考

时间:2019-05-09 17:32:07

标签: angular

我正在编写Angular 7应用程序。我想知道是否有一种方法可以打印活动对象的引用(在我的情况下是一种服务https://angular.io/guide/architecture-services)。

我需要这样做来了解内存中是否存在该对象的许多实例,因为我遇到了一些麻烦,调试无法帮助我发现问题。 我的猜测是我在内存中有更多相同类的实例。不幸的是,只是打印:

console.log(myService)

它不会在对象的内存引用中打印任何内容,因此我无法理解我所看到的是同一对象还是新对象。

是否有办法像从Chrome浏览器中获取内存快照时获取的那样?

3 个答案:

答案 0 :(得分:1)

  

它不会在对象的内存引用中打印任何内容,因此我无法理解我所看到的是同一对象还是新对象。

Angular不会复制服务,但是会复制模块,从而导致提供者重复。

这最常见于延迟加载的模块,我将在下面演示。

@NgModule({...}
export class SharedModule {
     provides: [MyService]
}

@NgModule({...}
export class AppModule {
    imports: [SharedModule]
}

@NgModule({...}
export class LazyModule {
    imports: [SharedModule]
}

在上述模块中,SharedModuleAppModule都使用LazyModule,但是路由器通过延迟加载来加载LazyModule

这里的问题是专门为SharedModule创建了LazyModule的新实例。它不会使用AppModule使用的相同引用,并且由于ShareModule具有提供者,因此它们将是 new 提供者。

您可以尝试向您的服务添加防护,以防止重复实例。

@Injector()
export class MyService {
    public constructor(@Optional() @SkipSelf() duplicate: MyService) {
         if(duplicate) {
             throw new Error('Service can not be duplicated');
         }
    }
}

此后,Angular添加了功能provideIn,该功能使您可以向根模块添加服务,并防止多次提供该服务。您可以为此更新注射器。

 @Injector({provideIn: 'root'})

在大多数情况下,这可以正常工作。

  

我需要这样做来了解内存中是否存在该对象的许多实例,因为我遇到了一些麻烦,调试无法帮助我找到问题。

您在评论中提到,这在Java中易于调试,但在JavaScript中则更抽象。

var x = new MyService();
var y = {...x};
var z = Object.assign({}, x);

查看上面的代码。 MyService有多少个实例?

从JavaScript角度来看,有3个,因为x !== y && x !== z && y !== z,但是从Java角度来看,只有1个实例。那是因为构造函数只使用了一次。

在Angular中,用@Injector({...})声明的服务将始终为依赖项注入器中的每个提供者调用其构造函数。因此,如果要跟踪 instances 的数量,最好从构造函数中记录该信息。

答案很长,但这是我的看法。

答案 1 :(得分:0)

providedIn注释自角度6起可用。

如果未在任何特定模块中包含您的服务,则角度编译器将确定该服务是否在应用程序上使用,并初始化首次使用时间。

@Injectable({
 providedIn: 'root',
})

答案 2 :(得分:0)

我认为角度服务必须是单音,因此内存中每个服务只有一个对象。