如何为Angular HttpClient设置baseUrl?

Ste*_*rov 53 angular angular-httpclient

我没有在文档中找到为所有http请求设置基本API URL的方法.是否可以使用Angular HttpClient?

The*_*eal 73

使用新的HttpClient拦截器.

创建一个适当的注射剂,实现HttpInterceptor:

import {Injectable} from '@angular/core';
import {HttpEvent, HttpInterceptor, HttpHandler, HttpRequest} from '@angular/common/http';
import {Observable} from 'rxjs/Observable';

@Injectable()
export class APIInterceptor implements HttpInterceptor {
  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {

    const apiReq = req.clone({ url: `your-api-url/${req.url}` });
    return next.handle(apiReq);
  }
}
Run Code Online (Sandbox Code Playgroud)

HttpInterceptor可以克隆请求并根据需要进行更改,在这种情况下,我为所有http请求定义了一个默认路径.

为HttpClientModule提供以下配置:

providers: [{
      provide: HTTP_INTERCEPTORS,
      useClass: APIInterceptor,
      multi: true,
    }
  ]
Run Code Online (Sandbox Code Playgroud)

现在您的所有请求都将从此开始 your-api-url/

  • 这很棒!但有一件事,你不需要在这里使用Injectable装饰器,只有当你想要把东西注入装饰类时才需要它. (6认同)
  • 我看到这段代码时哭了.为什么我们不能创建一个具有`baseUrl`属性的客户端实例,而不是这个类似中间件的解决方案,这个解决方案在这样一个简单的用例中位于顶层 (5认同)
  • 我是唯一一个通过为每个请求执行“req.clone”而看到开销的人吗?HttpRequest 似乎是不可变的,所以对于大请求,我想会增加大量的处理开销?我知道它看起来很整洁,但这不是增加了无用的重新处理吗?我错过了什么吗?仅供参考:我是前台菜鸟 (3认同)
  • 并且,如果您希望不同的HttpClient使用不同的基本URL,您将如何管理它?在要求可注射设备打开的某种标记中,需要使用多个注射器。在我看来一点也不优雅。 (2认同)

Ale*_*xei 23

基于TheUnreal非常有用的答案,可以编写拦截器以通过DI获取基本URL:

@Injectable()
export class BaseUrlInterceptor implements HttpInterceptor {

    constructor(
        @Inject('BASE_API_URL') private baseUrl: string) {
    }

    intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {

        const apiReq = request.clone({ url: `${this.baseUrl}/${request.url}` });
        return next.handle(apiReq);
    }
}
Run Code Online (Sandbox Code Playgroud)

BASE_API_URL 可以由应用程序模块提供:

providers: [
    { provide: "BASE_API_URL", useValue: environment.apiUrl }
]
Run Code Online (Sandbox Code Playgroud)

environment生成项目时CLI自动创建的对象在哪里:

export const environment = {
  production: false,
  apiUrl: "..."
}; 
Run Code Online (Sandbox Code Playgroud)

  • @Alexei-checkCodidact 您不需要注入 `BASE_API_URL` 您可以简单地使用 `environment.apiUrl` 访问它,该值将根据您当前的环境而变化。 (2认同)

Neu*_*ino 8

为什么不创建一个具有可配置 baseUrl 的 HttpClient 子类?这样,如果您的应用程序需要与多个服务通信,您可以为每个服务使用不同的子类,或者创建单个子类的多个实例,每个实例具有不同的配置。

@Injectable()
export class ApiHttpClient extends HttpClient {
  public baseUrl: string;

  public constructor(handler: HttpHandler) {
    super(handler);

    // Get base url from wherever you like, or provision ApiHttpClient in your AppComponent or some other high level
    // component and set the baseUrl there.
    this.baseUrl = '/api/';
  }

  public get(url: string, options?: Object): Observable<any> {
    url = this.baseUrl + url;
    return super.get(url, options);
  }
}
Run Code Online (Sandbox Code Playgroud)

  • 其他任何想这样做的人请不要这样做。HttpClient 是一个“Final”类,Angular 不建议扩展“Final”类,因为其内部实现可能会发生变化。更多相关信息:https://github.com/angular/angular/blob/13.1.1/docs/PUBLIC_API.md#final-classes (2认同)

小智 6

摘自 Visual Studio 2017 asp.net core webapi angular 示例应用程序。

在 Main.ts 中包含以下几行

export function getBaseUrl() {
  return document.getElementsByTagName('base')[0].href;
}

const providers = [
  { provide: 'BASE_URL', useFactory: getBaseUrl, deps: [] }
];
Run Code Online (Sandbox Code Playgroud)

在您的组件中

  constructor(http: HttpClient, @Inject('BASE_URL') baseUrl: string) {
    http.get<WeatherForecast[]>(baseUrl + 'api/SampleData/WeatherForecasts').subscribe(result => {
      this.forecasts = result;
    }, error => console.error(error));
  }
Run Code Online (Sandbox Code Playgroud)

我完整的 main.ts 代码如下所示

import { enableProdMode } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';

import { AppModule } from './app/app.module';
import { environment } from './environments/environment';

export function getBaseUrl() {
  return document.getElementsByTagName('base')[0].href;
}

const providers = [
  { provide: 'BASE_URL', useFactory: getBaseUrl, deps: [] }
];

if (environment.production) {
  enableProdMode();
}

platformBrowserDynamic()
  .bootstrapModule(AppModule)
  .catch(err => console.error(err));

Run Code Online (Sandbox Code Playgroud)

我的组件代码如下所示

import { Component, Inject } from '@angular/core';
import { HttpClient } from '@angular/common/http';

@Component({
  selector: 'fetch-weather',
  templateUrl: './weather.component.html',
  styleUrls: ['./weather.component.scss']
})

export class WeatherComponent {
  public forecasts: WeatherForecast[];

  constructor(http: HttpClient, @Inject('BASE_URL') baseUrl: string) {
    http.get<WeatherForecast[]>(baseUrl + 'api/SampleData/WeatherForecasts').subscribe(result => {
      this.forecasts = result;
    }, error => console.error(error));
  }
}

interface WeatherForecast {
  dateFormatted: string;
  temperatureC: number;
  temperatureF: number;
  summary: string;
}

Run Code Online (Sandbox Code Playgroud)


Hak*_*kej 6

每个跟随阿列克谢的人都回答并不能像我一样让它工作 - 这是因为你还必须将这个元素添加到提供者数组中

{
  provide: HTTP_INTERCEPTORS,
  useClass: BaseUrlInterceptor,
  multi: true
}
Run Code Online (Sandbox Code Playgroud)

不幸的是,我的声誉太低,无法在他的回答中添加评论。

  • 我投了赞成票来帮助你,我的朋友。 (3认同)
  • @BraianSilva 谢谢哥们,你才是我现在可以评论的原因! (2认同)

ski*_*nes 5

您不一定需要使用带有HttpClient基本URL,文档说您只需要指定请求的api部分,如果要在同一服务器上进行调用,则很简单,例如:

this.http.get('/api/items').subscribe(data => { ...

但是,您可以根据需要指定基本URL。

我对此有2条建议:

1。具有静态类属性的帮助器类。

export class HttpClientHelper{

    static baseURL: string = 'http://localhost:8080/myApp';
}


this.http.get(`${HttpClientHelper.baseURL}/api/items`);//in your service class
Run Code Online (Sandbox Code Playgroud)

2。具有class属性的基类,因此任何新服务都应对其进行扩展:

export class BackendBaseService {

  baseURL: string = 'http://localhost:8080/myApp';

  constructor(){}
Run Code Online (Sandbox Code Playgroud)

}

@Injectable()
export class ItemsService extends BackendBaseService{

  constructor(private http: HttpClient){  
    super();
  }

  public listAll(): Observable<any>{    
    return this.http.get(`${this.baseURL}/api/items`);
  }

}
Run Code Online (Sandbox Code Playgroud)


Ant*_*Lee 2

我认为没有默认的方法可以做到这一点。执行 HttpService,在里面您可以定义默认 URL 的属性,并使用您的属性 URL 调用 http.get 和其他方法。然后注入HttpService而不是HttpClient