我正在编写Angular 7应用程序。我想知道是否有一种方法可以打印活动对象的引用(在我的情况下是一种服务https://angular.io/guide/architecture-services)。
我需要这样做来了解内存中是否存在该对象的许多实例,因为我遇到了一些麻烦,调试无法帮助我发现问题。 我的猜测是我在内存中有更多相同类的实例。不幸的是,只是打印:
console.log(myService)
它不会在对象的内存引用中打印任何内容,因此我无法理解我所看到的是同一对象还是新对象。
是否有办法像从Chrome浏览器中获取内存快照时获取的那样?
答案 0 :(得分:1)
它不会在对象的内存引用中打印任何内容,因此我无法理解我所看到的是同一对象还是新对象。
Angular不会复制服务,但是会复制模块,从而导致提供者重复。
这最常见于延迟加载的模块,我将在下面演示。
@NgModule({...}
export class SharedModule {
provides: [MyService]
}
@NgModule({...}
export class AppModule {
imports: [SharedModule]
}
@NgModule({...}
export class LazyModule {
imports: [SharedModule]
}
在上述模块中,SharedModule
和AppModule
都使用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)
我认为角度服务必须是单音,因此内存中每个服务只有一个对象。