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) {
  }.......

查看此答案