如何在角4应用程序中存储api的根URL?

Ash*_*Raj 20 angular

我遵循官方教程并为Apis提供服务,但Api的绝对URL在服务中是硬编码的.

我想在某处保留Api的基本URL,以便我可以在调用之前将其附加到每个服务的url路径中.我还需要在建造之前(或建筑之后)更改Api的基本网址.

我试图将它放在sessionstorage中,但这是一个坏主意,因为任何人都可以更改它,我的应用程序将开始进入其他域.

所以我保持硬编码并在git上放置一个后推钩以在构建后替换url.但它更像是黑客而不是解决方案.

我可以将文件放在angular的根目录中,并将Api url放在json格式中.并将其包含在每个服务中,以便我可以从git中排除文件,并且每个队友和构建服务器可以拥有自己的文件具有不同的URL.

这应该是什么建议的方式?

Mik*_*sky 22

在Angular 4.3发布后,我们有可能使用HttpClient拦截器.这种方法的优点是避免导入/注入API_URL是api调用的所有服务.

这是我的基本实现:

@Injectable()
export class ApiUrlInterceptor implements HttpInterceptor {
constructor(@Inject(API_URL) private apiUrl: string) {}

  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    req = req.clone({url: this.prepareUrl(req.url)});
    return next.handle(req);
  }

  private isAbsoluteUrl(url: string): boolean {
    const absolutePattern = /^https?:\/\//i;
    return absolutePattern.test(url);
  }

  private prepareUrl(url: string): string {
    url = this.isAbsoluteUrl(url) ? url : this.apiUrl + '/' + url;
    return url.replace(/([^:]\/)\/+/g, '$1');
  }
}
Run Code Online (Sandbox Code Playgroud)

InjectionToken声明:

export const API_URL = new InjectionToken<string>('apiUrl');
Run Code Online (Sandbox Code Playgroud)

提供者注册:

{provide: API_URL, useValue: environment.apiUrl}
{provide: HTTP_INTERCEPTORS, useClass: ApiUrlInterceptor, multi: true, deps: [API_URL]}
Run Code Online (Sandbox Code Playgroud)

Environment.ts:

export const environment = {
 production: false,
 apiUrl: 'some-dev-api'
};
Run Code Online (Sandbox Code Playgroud)

  • 现在还不确定.我将此代码放在app.module.ts中.我将检查这个决定是否足够可扩展,并在稍后发表评论. (2认同)

Mas*_*mar 11

在哪里存储的角度配置Dave的笔记本电脑在哪里存储的角度配置

因为这是一个常见的问题,因为它经常被错误地做,因为有一个很好的替代方案,今天我想讨论在哪里存储 Angular 配置。您知道,当您从本地开发环境转移到开发、QA 和生产服务器时,所有这些信息都会发生变化吗?

有一个地方!

错误的地方 我知道这很诱人,但是 environment.ts 和 environment.prod.ts 文件从来没有用于配置信息,除了告诉运行时您正在运行代码的生产版本而不是在本地开发代码。是的,我知道可以为您的不同环境创建一个文件,您可以有效地将该文件用于您的配置信息。但是,仅仅因为你可以,并不意味着你应该。

在理想的世界中,您将构建一个候选版本并将其放置在您的开发服务器上,然后将其从那里移至 QA,然后移至生产。您永远不会重建应用程序。您希望绝对确定您在开发环境中测试的代码是您在 QA 环境中运行的代码,并且您在 QA 环境中运行的代码是在生产环境中运行的代码。您想确定地知道某些东西不起作用的唯一可能原因是配置信息不正确。

还有其他降低风险的方法,但它们都涉及重新编译代码并标记您的存储库,以便您可以获得相同的代码。这在没有更好的方法时有效。但是,还有更好的方法!

相反在哪里? 如果我们不能把我们的配置信息放在我们的代码中,我们把它放在哪里?显然在您的代码之外。这给我们留下了几种解决方案。一种是创建一个静态 json 文件,当代码部署到每个环境时,该文件会被复制到您的 dist 目录中。我看到的另一个工作是将代码放在数据库中。数据库方法的优点是您可以拥有一个数据库来处理所有应用程序甚至所有环境的配置信息。在它之上放置一个良好的管理 GUI,您可以轻松更改配置,甚至无需部署文件。

跨越障碍 既然您已将配置信息放在外部位置,您就会意识到需要发出 GET 请求来检索该信息。您可能很快就会意识到,您的应用程序一启动就需要这些配置信息。也许将这些信息放在外部文件中毕竟不是一个好主意?

嗯,没那么快!

Angular 中有一个鲜为人知的 API 功能,它允许我们预先加载内容,并且实际上会等到加载完成后再继续我们的代码。

APP_INITIALIZER APP_INITIALIZER 是一种多提供程序类型,可让您指定返回承诺的工厂。当 promise 完成时,应用程序将继续。因此,当您到达代码中需要配置信息的地方时,您可以确定它已被加载。它很光滑。

import { APP_INITIALIZER } from '@angular/core'

@NgModule({
    ....
    providers: [
        ...
        {
            provide: APP_INITIALIZER,
            useFactory: load,
            multi: true
        }
    ]
)
Run Code Online (Sandbox Code Playgroud)

其中 load 是一个函数,它返回一个返回 Promise 的函数。promise 函数加载您的配置信息并将其存储在您的应用程序中。加载配置后,您可以使用 resolve(true) 来解析 promise。

最后一点非常重要。如果你弄错了,代码不会等待它完成加载再继续。useFactory 指向一个函数,该函数返回一个返回 Promise 的函数!

multi: true 是因为 APP_INITIALIZER 允许此提供程序的多个实例。它们都同时运行,但在所有 Promise 都已解决之前,代码不会在 APP_INTITIALIZER 之外继续运行。

一个例子。 现在,作为一个讨论点,让我们假设您有一个基于 Angular CLI 的常规项目,并且您需要在 REST 端点的基本位置加载。您可能有一个如下所示的 config.json 文件:

{
    "baseUrl": "https://davembush.github.io/api"
}
Run Code Online (Sandbox Code Playgroud)

您将为要部署到的每个环境创建不同的其中一个,并且作为部署过程的一部分,您将适当的文件复制到 config.json 中部署所有 Angular CLI 的同一位置生成的静态文件。

Basic App Initializer 现在,我们要做的是在运行时使用 APP_INITIALIZER 加载这个配置文件。为此,让我们在 app.module.ts 文件中添加一个 APP_INITIALIZER 提供程序。

import { APP_INITIALIZER } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppComponent } from './app.component';

function load() {

}

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule
  ],
  providers: [{
    provide: APP_INITIALIZER,
    useFactory: load,
    multi: true
  }],
  bootstrap: [AppComponent]
})
export class AppModule { }
Run Code Online (Sandbox Code Playgroud)

完整的结果代码 以防万一我遗漏了一个步骤,或者您丢失了,或者您真正关心的只是代码,以便您可以复制和粘贴它。

import { APP_INITIALIZER } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { HttpClientModule, HttpClient } from '@angular/common/http';

import { AppComponent } from './app.component';
import { ConfigService } from './config.service';
import { of, Observable, ObservableInput } from '../../node_modules/rxjs';
import { map, catchError } from 'rxjs/operators';

function load(http: HttpClient, config: ConfigService): (() => Promise<boolean>) {
  return (): Promise<boolean> => {
    return new Promise<boolean>((resolve: (a: boolean) => void): void => {
       http.get('./config.json')
         .pipe(
           map((x: ConfigService) => {
             config.baseUrl = x.baseUrl;
             resolve(true);
           }),
           catchError((x: { status: number }, caught: Observable<void>): ObservableInput<{}> => {
             if (x.status !== 404) {
               resolve(false);
             }
             config.baseUrl = 'http://localhost:8080/api';
             resolve(true);
             return of({});
           })
         ).subscribe();
    });
  };
}
@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    HttpClientModule
  ],
  providers: [{
      provide: APP_INITIALIZER,
      useFactory: load,
      deps: [
        HttpClient,
        ConfigService
      ],
      multi: true
    }
  ],
  bootstrap: [AppComponent]
})
export class AppModule { }
Run Code Online (Sandbox Code Playgroud)


Loo*_*lar 7

使用环境文件

如果您使用 cli,则应使用环境文件。通过配置 angular-cli.json 文件,您可以管理所有可用环境并创建新环境。例如,您可以创建一个 environment.dev.js 文件并将值存储在那里,通过让 git ignore 它,您团队中的任何成员都可以自定义一个。

说环境文件会覆盖原来的environment.js

请参阅此 SO 回答angular-cli for angular2 how to load environment variables


pen*_*han 5

通常我把它们放在 const 环境文件中。如果您使用的是 angular-cli,那么已经为您提供了此功能,如果没有,您可以创建自己的:

export const environment = {  
  production: false,
  api: 'http://localhost:4200/api/'
};
Run Code Online (Sandbox Code Playgroud)

您可以有多个环境文件,例如environment.development.ts,然后使用 angular-cli 运行:

ng build --environment=production
Run Code Online (Sandbox Code Playgroud)

如果您不使用 angular-cli,那么您肯定可以构建自己的类似的东西。