如何将动态变量从服务传递给 http_interceptor

How to pass dynamic variable to http_interceptor from a service

我有多个 angular 项目,每个项目都有调用相同 API 的服务。 我一直在添加一个 header 来请求以确定请求是从哪个应用程序发送的。 所以我一直在尝试创建一个具有 基本服务 class 的库来设置 header 值


    @Injectable({ providedIn: "root" })
    export class AppbaseService {
        scope: string; 
        constructor(@Inject(forwardRef(()=>'scope')) scope:string) { 
            this.scope = scope;
        }
        getScope():string{
            return this.scope;
        }
    }

和一个 http 拦截器 将该动态值作为 header

附加到请求

    @Injectable()
    export class ScopeInterceptor implements HttpInterceptor {
    
        constructor(private appBaseService: AppbaseService) {
        }
    
        intercept(req: HttpRequest<any>,
            next: HttpHandler): Observable<HttpEvent<any>> {
    
            const clonedRequest = req.clone({
                headers: req.headers.append(
                    'Scope',
                    this.appBaseService.scope
                )
            });
            return next.handle(clonedRequest);
        }
    }

最后一个 factory 将动态值设置为 provider


    export function appValueFactory(baseService: AppbaseService) {
        console.log(baseService);
        return baseService.getScope();
    }

但我不知道如何在模块中设置提供程序并出现以下错误,这不是很有帮助。


    Uncaught Error: Can't resolve all parameters for qI: (?).
        at Jt (main.js:1)
        at e._getDependenciesMetadata (main.js:1)
        at e._getFactoryMetadata (main.js:1)
        at e.getProviderMetadata (main.js:1)
        at main.js:1
        at Array.forEach (<anonymous>)
        at e._getProvidersMetadata (main.js:1)
        at main.js:1
        at Array.forEach (<anonymous>)
        at e._getProvidersMetadata (main.js:1)

有人能给我指出正确的方向吗?

谢谢。

首先,“这是做什么用的:@Inject(forwardRef(()=>'scope'))? 在构造函数中你应该注入服务并且范围是一个字符串。

我知道 scope 是当前应用程序的字符串标识符,所以简单的解决方案是直接在拦截器中添加该字符串。

如果您希望使用服务来获取该字符串,问题将在 AppbaseService 内部,因为 scope 值是异步的(它在构造函数中填充)所以,如果您的代码尝试在创建 AppbaseService 之前调用 ScopeInterceptorscope 将是未定义的。

要解决此问题,请将服务 return 设为 Observable(我们假设 scopeService.getAppScope() return 此应用的范围字符串)

    export class AppbaseService {
        scope = new BehaviorSubject<string>('');
        constructor(private scopeService: ScopeService) { 
            this.scope.next(scopeService.getAppScope());
        }
        getScope$(): Observable<string> {
            return this.scope.asObservable();
        }
    }

并且从拦截器使用这个异步函数并且return也是一个 Observable:

        intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
            return this.appBaseService.getScope$().pipe(
              filter(scope => !!scope), 
              take(1), 
              switchMap(scope => {
                const clonedRequest = req.clone({
                  headers: req.headers.append('Scope',scope)
                });
                return next.handle(clonedRequest);
            }))
        }

rxjs函数解释:

  • filter用于过滤未定义的值:当范围尚未定义时,不要继续管道。
  • take(1):一旦接收到值,只消耗一次observable然后完成。
  • switchMap:从作用域 observable 和 returns 另一个 observable 中获取值 HttpEvent