electron NG0200:在DI中检测到InjectionToken HTTP_INTERCEPTORS的循环依赖关系

qncylg1j  于 2022-12-08  发布在  Electron
关注(0)|答案(1)|浏览(180)
Angular CLI: 11.0.1
Node: 14.8.0
OS: darwin x64

Angular: 11.0.0
... animations, cdk, common, compiler, compiler-cli, core, forms
... language-service, material, platform-browser
... platform-browser-dynamic, router
Ivy Workspace: Yes

Package                         Version
---------------------------------------------------------
@angular-devkit/architect       0.1002.0
@angular-devkit/build-angular   0.1100.1
@angular-devkit/core            10.2.0
@angular-devkit/schematics      11.0.1
@angular/cli                    11.0.1
@schematics/angular             11.0.1
@schematics/update              0.1100.1
rxjs                            6.6.3
typescript                      4.0.5

当我将translateService与httpInterceptor一起使用时,出现以下错误:
NG0200:在DI中检测到InjectionToken HTTP_INTERCEPTORS的循环依赖关系
如果我不使用translateService,它工作得很好,有人能帮我解决这个问题吗?下面是代码
app.component.ts

import { Component } from '@angular/core';
import { ElectronService } from './services';
import { TranslateService } from '@ngx-translate/core';
import { AppConfig } from '../environments/environment';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent {
  constructor(
    private electronService: ElectronService,
    private translate: TranslateService
  ) {
    this.translate.setDefaultLang('en');
    console.log('AppConfig', AppConfig);
  }
}

core.module.ts

import {InjectionToken, NgModule} from '@angular/core';
import {CommonModule} from '@angular/common';
import {BrowserModule} from '@angular/platform-browser';
import {FormsModule} from '@angular/forms';
import {HttpClient, HttpClientModule} from '@angular/common/http';
import {SharedModule} from '../shared/shared.module';
import {AppRoutingModule} from '../app-routing.module';
import {TranslateLoader, TranslateModule} from '@ngx-translate/core';
import {TranslateHttpLoader} from '@ngx-translate/http-loader';
import {AppStoreModule} from '../store/app-store.module';
import {ViewsModule} from '../views/views.module';
import {httpInterceptorProvides} from '../services/http-interceptor';
import {API_BASE_URL} from '../services/service.module';

// AoT requires an exported function for factories
export function HttpLoaderFactory(http: HttpClient): TranslateHttpLoader {
  return new TranslateHttpLoader(http, '../../assets/i18n/', '.json');
}

@NgModule({
  declarations: [],
  imports: [
    CommonModule,
    BrowserModule,
    FormsModule,
    HttpClientModule,
    AppStoreModule,
    SharedModule,
    ViewsModule,
    AppRoutingModule,
    TranslateModule.forRoot({
      loader: {
        provide: TranslateLoader,
        useFactory: HttpLoaderFactory,
        deps: [HttpClient]
      }
    })
  ],
  providers: [
    {
      provide: API_BASE_URL,
      useValue: 'https://demo.xx.com'
    },
    httpInterceptorProvides,
  ],
  exports: [AppRoutingModule, SharedModule]
})
export class CoreModule {
}

httpinterceptor.ts

import {Inject, Injectable} from '@angular/core';
import {
  HttpRequest,
  HttpHandler,
  HttpEvent,
  HttpInterceptor
} from '@angular/common/http';
import {Observable} from 'rxjs';
import {switchMap} from 'rxjs/operators';
import {AuthService} from '../auth.service';
import {API_BASE_URL} from '../service.module';

@Injectable()
export class CommonInterceptor implements HttpInterceptor {
  skipUrl: string[];

  constructor(private auth: AuthService, @Inject(API_BASE_URL) private uri: string) {
    this.skipUrl = ['/oauth/token', 'assets/i18n'];
  }

  intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    const req = request.clone({
      setHeaders: {
        'Accept': 'dddd'
      },
      url: this.uri + request.url
    });
    // return next.handle(req);

    if (this.isSkipAuth(req.url)) {
      return next.handle(req);
    } else {
      return this.auth.getToken()
        .pipe(
          switchMap((access_token) => {
            const reqA = req.clone({
              setHeaders: {
                'Authorization': 'Bearer ' + access_token
              }
            });
            return next.handle(reqA);
          })
        );
    }
  }

  isSkipAuth(url: string): boolean {
    let isMatch = false;
    this.skipUrl.forEach((reg_url: string) => {
      if (!isMatch) {
        if (url.search(reg_url) >= 0) {
          isMatch = true;
        }
      }
    });
    return isMatch;
  }
}

auth.service.ts

import {Injectable} from '@angular/core';
import {HttpClient} from '@angular/common/http';
import {Observable, of} from 'rxjs';
import {ElectronService} from './electron/electron.service';
import {map, pluck, tap} from 'rxjs/operators';
import {ResponseType} from './data-types/common.type';

export interface TokenModel {
  access_token: string; // access_token
  expires: number; // 
  expires_in: number; // 
}


@Injectable({
  providedIn: 'root'
})
export class AuthService {
  elStoreIns: any;

  constructor(private http: HttpClient, private elService: ElectronService) {
    this.elStoreIns = this.elService.elStore;
  }

  getToken(): Observable<string> {
    const now = Date.now();
    const tokenStore: TokenModel = this.elStoreIns.get('token');
    if (tokenStore instanceof Object) {
      if ((now - tokenStore.expires) <= 7100 * 1000) {
        return of(tokenStore.access_token);
      }
    }
    return this.requestToken();
  }

  requestToken(): Observable<string> {
    return this.http.post<ResponseType>('/oauth/token', {
      client_ids: 1,
      client_secrets: 'ddd',
      grant_types: 'dddd'
    }).pipe(
      pluck('data'),
      tap((data: any) => {
        const tokenData: TokenModel = {
          access_token: data.access_token,
          expires_in: data.expires_in,
          expires: Date.now()
        };
        this.saveToken(tokenData);
      }),
      map(data => data.access_token)
    );
  }

  saveToken(tokenStore: TokenModel): void {
    this.elStoreIns.set('token', tokenStore);
  }
}
hgqdbh6s

hgqdbh6s1#

我不能100%确定它是否是一个有效的干净的解决方案,但是您可以尝试在“auth.service.ts”中自己示例化“HttpClient”。从您的构造函数中删除HttpClient,并尝试以下方法:

private http: HttpClient;

constructor(httpBackend: HttpBackend) {
    this.http = new HttpClient(httpBackend);
}

相关问题