【问题标题】:how to inject API_BASE_URL (a string) in an angular service如何在角度服务中注入 API_BASE_URL(字符串)
【发布时间】:2018-06-19 07:41:27
【问题描述】:

这个自动生成的服务(由 NSwagStudio)需要一个 API_BASE_URL(InjectionToken)值来执行 http 请求 我如何以及在哪里可以注入它?

/* tslint:disable */
//----------------------
// <auto-generated>
//     Generated using the NSwag toolchain v11.12.16.0 (NJsonSchema v9.10.19.0 (Newtonsoft.Json v9.0.0.0)) (http://NSwag.org)
// </auto-generated>
//----------------------
// ReSharper disable InconsistentNaming

import 'rxjs/add/observable/fromPromise';
import 'rxjs/add/observable/of';
import 'rxjs/add/observable/throw';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/toPromise';
import 'rxjs/add/operator/mergeMap';
import 'rxjs/add/operator/catch';

import { Observable } from 'rxjs/Observable';
import { Injectable, Inject, Optional, InjectionToken } from '@angular/core';
import { HttpClient, HttpHeaders, HttpParams, HttpResponse, HttpResponseBase, HttpErrorResponse } from '@angular/common/http';

export const API_BASE_URL = new InjectionToken<string>('API_BASE_URL');

@Injectable()
export class DocumentService {
    private http: HttpClient;
    private baseUrl: string;
    protected jsonParseReviver: ((key: string, value: any) => any) | undefined = undefined;

    constructor(@Inject(HttpClient) http: HttpClient, @Optional() @Inject(API_BASE_URL) baseUrl?: string) {
        this.http = http;
        this.baseUrl = baseUrl ? baseUrl : "";
    }

    getAll(): Observable<string[] | null> {
        let url_ = this.baseUrl + "/api/Document";
        url_ = url_.replace(/[?&]$/, "");

        let options_ : any = {
            observe: "response",
            responseType: "blob",
            headers: new HttpHeaders({
                "Content-Type": "application/json", 
                "Accept": "application/json"
            })
        };

        return this.http.request("get", url_, options_).flatMap((response_ : any) => {
            return this.processGetAll(response_);
        }).catch((response_: any) => {
            if (response_ instanceof HttpResponseBase) {
                try {
                    return this.processGetAll(<any>response_);
                } catch (e) {
                    return <Observable<string[] | null>><any>Observable.throw(e);
                }
            } else
                return <Observable<string[] | null>><any>Observable.throw(response_);
        });
    }

    protected processGetAll(response: HttpResponseBase): Observable<string[] | null> {
        ...........code
        ........
        ....
    }
}

有人可以给我一些关于 InjectioToken 如何工作以及如何将其注入此服务的超级快速提示吗?

Angular5 - Nswag

【问题讨论】:

    标签: angular nswag


    【解决方案1】:

    如上所述,最好将其放入您的环境设置中,然后 Angular 将根据您所处的环境替换适当的基本 url,例如在开发中:

    export const environment = {
    
        production: false,
        apiRoot: "https://localhost:1234",
    };
    

    然后你可以在你的提供者中使用 useValue (为简单起见,所有其他内容都被删除了):

    ...
    import { environment } from '@env/environment';
    
    @NgModule({
    
        imports: [ ... ],
    
        declarations: [ ... ],
    
        providers: [
    
            {
                provide: API_BASE_URL,
                useValue: environment.apiRoot
            },
            ...
        ]
    
        exports: [ ... ]
    })
    export class AppModule {}
    

    要使用如上所示的@env 别名,您需要在 tsconfig.json 中添加如下内容:

    {
        ...
        "compilerOptions": {
            "baseUrl": "src",
            "paths": {
                "@env/*": [ "environments/*" ]
            },
        etc...
    }
    

    并且 Angular 会根据使用的 ---env 标志替换相应的环境设置。

    【讨论】:

    • 嗨,马特,当我尝试实现您的代码时,API_BASE_URL 当然是未定义的并且无法编译。我应该从哪里导入它?谢谢
    • 嗨@Nico,已编辑我的答案以显示设置位置。
    • 嘿,马特,在 app.module 的 import 语句中,'@env/environment' 下的错误显示为 Cannot find module '@env/environment'
    • @atiyar - 刚刚尝试使用 ng8 并且上述工作正常 - 您需要确保 baseUrl 和 tsconfig 中的路径条目的组合指向环境文件夹。例如,如果您的 baseUrl 是“./”,那么您已经使用 ng cli 生成您的项目,您的路径条目将是“@env/*”:[“src/environments/*”]
    • 确保从 NSwag 生成的客户端导入 API_BASE_URL,例如 module.ts 文件中的 import { API_BASE_URL } from 'src/app/services/api.generated.clients';
    【解决方案2】:

    在父模块上为 API_BASE_URL 创建一个提供者

    export function getBaseUrl(): string {
      return AppConsts.baseUrl;
    }
    
    @NgModule({
      declarations: [AppComponent],
      imports: [BrowserModule],
      providers: [{ provide: API_BASE_URL, useFactory: getBaseUrl }],
       bootstrap: [AppComponent]
    })
    export class AppModule {}
    

    然后定义一个具有静态属性的 AppConsts 类

    export class AppConsts {
      static baseUrl = "your_api_base_url"; 
    }
    

    为我工作,希望对您有所帮助。该解决方案基于 aspnet 样板 Angular 项目,对我而言,它提供了最佳的架构标准。 我把angular project 的网址+specific code 的网址留在这里。

    【讨论】:

    • 但是如果我在每个文件中有几个不同的客户端文件和几个 API_BASE_URL 变量,我如何在一个模块文件中为它们中的每一个设置提供程序。会有冲突。我尝试使用“AP_BASE_URL”。另一件事是不需要工厂。您可以使用 useValue 代替工厂。然后您可以直接从环境中设置值或使用 AppConsts
    • 你如何为像OP的DocumentService这样的构造函数中具有@injector的组件编写测试
    【解决方案3】:

    将所有常量放在 environment.ts 和 environment.prod.ts 中的最佳做法。只需在您的服务中创建一个新属性并导入。您的代码将如下所示:

    // environment.ts
    export const environment = {
      production: false,
      API_BASE_URL: "baseUrlOfApiForDevelopment",
    };
    
    // environment.prod.ts
    export const environment = {
      production: false,
      API_BASE_URL: "baseUrlOfApiForProduction",
    };
    

    现在您需要在服务中导入才能使用它。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-10-04
      • 2020-01-03
      • 2019-01-11
      • 1970-01-01
      • 2023-03-29
      • 1970-01-01
      相关资源
      最近更新 更多