Ngrx Store as dependency in providers 导致循环依赖
Ngrx Store as dependency in providers causes cyclic dependency
我正在尝试通过提供应该注入 ngrx 存储的工厂函数来覆盖默认值 angular ErrorHandler
:
import { ErrorHandler } from "@angular/core";
[...]
{
provide: ErrorHandler,
useFactory: (store: Store<AppState>) => {
return Sentry.createErrorHandler({
showDialog: true,
dialogOptions: {},
});
},
deps: [Store],
},
但我收到循环依赖错误:
main.ts:42 Error: NG0200: Circular dependency in DI detected for Store. Find more at https://angular.io/errors/NG0200
at throwCyclicDependencyError (core.js:216)
at R3Injector.hydrate (core.js:11434)
at R3Injector.get (core.js:11257)
at injectInjectorOnly (core.js:4751)
at ɵɵinject (core.js:4755)
at injectArgs (core.js:4832)
at Object.factory (core.js:11522)
at R3Injector.hydrate (core.js:11438)
at R3Injector.get (core.js:11257)
at injectInjectorOnly (core.js:4751)
如何省略这个问题?我需要将商店中的某物提供给创建错误处理程序的工厂函数 (Sentry.createErrorHandler
)。
我发现的最简单的方法是实现自定义错误处理程序,因为 ngrx-store
使用 Angulars EventHandler
例如
SentryErrorHandler
import { ErrorHandler, Injectable } from "@angular/core";
import * as Sentry from "@sentry/angular";
import { Integrations } from "@sentry/tracing";
@Injectable()
export class SentryErrorHandler implements ErrorHandler {
constructor() {
Sentry.init({
dsn: "https://[your-sentry-dsn-here]",
integrations: [
new Integrations.BrowserTracing({
tracingOrigins: ["localhost", "other-test-urls"],
routingInstrumentation: Sentry.routingInstrumentation
})
]
});
}
handleError(error: Error) {
Sentry.captureException(error);
}
}
然后在你的 app.module
providers: [
{
provide: ErrorHandler,
useClass: SentryErrorHandler
}
]
要测试一个示例,将在调用服务的 Effect
中创建一个不正确的 url,而不是 catchError
以查看它是否在 Sentry 中弹出,例如
@Injectable()
export class SettingsEffects {
constructor(private actions$: Actions,
private settingsService: settingsService) {
}
loadSettings$ = createEffect(() => this.actions$
.pipe(
ofType(settingsActions.loadSettings),
mergeMap(() => this.settingsService.get()
.pipe(
map((response) => settingsActions.loadSettingsSuccess({ payload: response})),
//catchError((error) => of(settingsActions.loadSettingsFailed({ payload: error}))) //commented out should go to Sentry instead
))
));
}
更新
似乎 ErrorHandler
是在提供者尝试通过添加 Injector
作为构造函数参数
之前在生命周期的早期创建的
@Injectable()
export class SentryErrorHandler implements ErrorHandler {
//store property to use in handleError
private get _store() {
return this.injector.get(Store);
}
constructor(private injector: Injector) {
}.......
查看此答案
我正在尝试通过提供应该注入 ngrx 存储的工厂函数来覆盖默认值 angular ErrorHandler
:
import { ErrorHandler } from "@angular/core";
[...]
{
provide: ErrorHandler,
useFactory: (store: Store<AppState>) => {
return Sentry.createErrorHandler({
showDialog: true,
dialogOptions: {},
});
},
deps: [Store],
},
但我收到循环依赖错误:
main.ts:42 Error: NG0200: Circular dependency in DI detected for Store. Find more at https://angular.io/errors/NG0200
at throwCyclicDependencyError (core.js:216)
at R3Injector.hydrate (core.js:11434)
at R3Injector.get (core.js:11257)
at injectInjectorOnly (core.js:4751)
at ɵɵinject (core.js:4755)
at injectArgs (core.js:4832)
at Object.factory (core.js:11522)
at R3Injector.hydrate (core.js:11438)
at R3Injector.get (core.js:11257)
at injectInjectorOnly (core.js:4751)
如何省略这个问题?我需要将商店中的某物提供给创建错误处理程序的工厂函数 (Sentry.createErrorHandler
)。
我发现的最简单的方法是实现自定义错误处理程序,因为 ngrx-store
使用 Angulars EventHandler
例如
SentryErrorHandler
import { ErrorHandler, Injectable } from "@angular/core";
import * as Sentry from "@sentry/angular";
import { Integrations } from "@sentry/tracing";
@Injectable()
export class SentryErrorHandler implements ErrorHandler {
constructor() {
Sentry.init({
dsn: "https://[your-sentry-dsn-here]",
integrations: [
new Integrations.BrowserTracing({
tracingOrigins: ["localhost", "other-test-urls"],
routingInstrumentation: Sentry.routingInstrumentation
})
]
});
}
handleError(error: Error) {
Sentry.captureException(error);
}
}
然后在你的 app.module
providers: [
{
provide: ErrorHandler,
useClass: SentryErrorHandler
}
]
要测试一个示例,将在调用服务的 Effect
中创建一个不正确的 url,而不是 catchError
以查看它是否在 Sentry 中弹出,例如
@Injectable()
export class SettingsEffects {
constructor(private actions$: Actions,
private settingsService: settingsService) {
}
loadSettings$ = createEffect(() => this.actions$
.pipe(
ofType(settingsActions.loadSettings),
mergeMap(() => this.settingsService.get()
.pipe(
map((response) => settingsActions.loadSettingsSuccess({ payload: response})),
//catchError((error) => of(settingsActions.loadSettingsFailed({ payload: error}))) //commented out should go to Sentry instead
))
));
}
更新
似乎 ErrorHandler
是在提供者尝试通过添加 Injector
作为构造函数参数
@Injectable()
export class SentryErrorHandler implements ErrorHandler {
//store property to use in handleError
private get _store() {
return this.injector.get(Store);
}
constructor(private injector: Injector) {
}.......
查看此答案