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
Run Code Online (Sandbox Code Playgroud)
当我将 translateService 与 httpInterceptor 一起使用时,出现此错误:
NG0200:检测到针对 InjectionToken HTTP_INTERCEPTORS 的 DI 循环依赖
如果我不使用 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);
}
}
Run Code Online (Sandbox Code Playgroud)
核心模块.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 {
}
Run Code Online (Sandbox Code Playgroud)
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;
}
}
Run Code Online (Sandbox Code Playgroud)
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);
}
}
Run Code Online (Sandbox Code Playgroud)
首先,一旦服务构造函数中抛出错误, Angular 就会引发“NG0200:循环依赖”错误。即使这与任何依赖注入无关。
现在关于拦截器,简而言之,您不能在拦截器本身中使用服务,HttpClient因为HttpClient依赖于拦截器。解决方法是提供一个HttpClient没有任何拦截器的全新实例。
jul*_*uli -2
我不确定它是否是一个有效且干净的解决方案,但您可以尝试在“auth.service.ts”中自行实例化“HttpClient”。从构造函数中删除 HttpClient,然后尝试以下方法:
private http: HttpClient;
constructor(httpBackend: HttpBackend) {
this.http = new HttpClient(httpBackend);
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3238 次 |
| 最近记录: |