Bu sorunu yıllar önce ben katılmadan önce yaşadık ve kullanıcı ve çevre bilgileri için yerel depolama kullanan bir çözüm bulduk. Tam olarak açısal 1.0 gün. Eskiden çalışma zamanında dinamik olarak bir js dosyası oluşturuyorduk ve bu daha sonra oluşturulan api url'lerini global bir değişkene yerleştirirdi. Bugünlerde biraz daha fazla OOP kullanıyoruz ve yerel depolamayı hiçbir şey için kullanmayın.
Hem ortamı belirlemek hem de api url oluşturmak için daha iyi bir çözüm yarattım.
Bu nasıl farklılık gösterir?
Config.json dosyası yüklenmedikçe uygulama yüklenmeyecektir. Daha yüksek bir SOC derecesi oluşturmak için fabrika işlevlerini kullanır. Bunu bir hizmet olarak özetleyebilirim, ancak dosyanın farklı bölümleri arasındaki tek benzerlik, dosyada birlikte var olmaları olduğunda hiçbir neden görmedim. Bir fabrika işlevine sahip olmak, bir işlevi kabul edebiliyorsa işlevi doğrudan bir modüle geçirmemi sağlar. Son olarak, fabrika fonksiyonları kullanıma hazır olduğunda InjectionTokens'ı kurmak için daha kolay bir zamanım var.
Dezavantajlar?
Yapılandırmak istediğiniz modül bir fabrika işlevinin forRoot () veya forChild () 'e geçirilmesine izin vermiyorsa ve başka bir yol yoksa, bu kurulumu (ve diğer yanıtların çoğunu) kullanırken şansınız kalmaz. bir fabrika işlevini kullanarak paketi yapılandırın.
Talimatlar
- Bir json dosyasını almak için getirme özelliğini kullanarak nesneyi pencerede depoluyorum ve özel bir olay oluşturuyorum. - whatwg-fetch'i kurmayı ve IE uyumluluğu için polyfills.ts dosyanıza eklemeyi unutmayın
- Özel etkinliği dinleyen bir olay dinleyicisine sahip olun.
- Olay dinleyicisi olayı alır, bir gözlemlenebilir nesneye geçmek için pencereden nesneyi alır ve pencerede neyin depolandığını siler.
- Bootstrap Açısal
- Çözümümün gerçekten farklı olmaya başladığı yer burası -
- Yapısı config.json'unuzu temsil eden bir arabirimi dışa aktaran bir dosya oluşturun - tür tutarlılığına gerçekten yardımcı olur ve sonraki kod bölümü bir tür gerektirir ve belirtmeyin
{}veya anydaha somut bir şey belirtebileceğinizi bildiğiniz zaman
- Ayrıştırılmış json dosyasını 3. adımda ileteceğiniz BehaviorSubject'i oluşturun.
- SOC'yi korumak için yapılandırmanızın farklı bölümlerine referans vermek için fabrika işlevlerini kullanın
- Fabrika işlevlerinizin sonucuna ihtiyaç duyan sağlayıcılar için InjectionTokens oluşturun
- ve / veya -
- Fabrika işlevlerini doğrudan forRoot () veya forChild () yöntemlerinde bir işlevi kabul edebilen modüllere aktarın.
- main.ts
Bir olay dinleyicisi oluşturmadan önce, ana.ts içindeki kod çalıştırılmadan önce pencerenin ["ortam"] başka yollarla doldurulduğu bir çözüm olasılığına izin vermek için pencerenin ["ortam"] doldurulmadığını kontrol ediyorum.
import { enableProdMode } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app/app.module';
import { configurationSubject } from './app/utils/environment-resolver';
var configurationLoadedEvent = document.createEvent('Event');
configurationLoadedEvent.initEvent('config-set', true, true);
fetch("../../assets/config.json")
.then(result => { return result.json(); })
.then(data => {
window["environment"] = data;
document.dispatchEvent(configurationLoadedEvent);
}, error => window.location.reload());
if(!window["environment"]) {
document.addEventListener('config-set', function(e){
if (window["environment"].production) {
enableProdMode();
}
configurationSubject.next(window["environment"]);
window["environment"] = undefined;
platformBrowserDynamic().bootstrapModule(AppModule)
.catch(err => console.log(err));
});
}
--- çevre çözücüler.ts
Artıklık için ["ortam"] penceresini kullanarak BehaviorSubject'e bir değer atıyorum. Yapılandırmanızın önceden yüklenmiş olduğu ve main.ts içindeki kod da dahil olmak üzere Angular uygulama kodunuzun herhangi biri çalıştırıldığında pencere ["ortam"] zaten doldurulmuş olan bir çözüm geliştirebilirsiniz.
import { BehaviorSubject } from "rxjs";
import { IConfig } from "../config.interface";
const config = <IConfig>Object.assign({}, window["environment"]);
export const configurationSubject = new BehaviorSubject<IConfig>(config);
export function resolveEnvironment() {
const env = configurationSubject.getValue().environment;
let resolvedEnvironment = "";
switch (env) {
}
return resolvedEnvironment;
}
export function resolveNgxLoggerConfig() {
return configurationSubject.getValue().logging;
}
- app.module.ts - Daha kolay anlaşılması için kaldırıldı
Eğlenceli gerçek! NGXLogger'ın eski sürümleri, bir nesneyi LoggerModule.forRoot () 'a iletmenizi gerektiriyordu. Aslında, LoggerModule hala var! NGXLogger, kurulum için fabrika işlevini kullanmanıza izin veren, geçersiz kılabileceğiniz LoggerConfig'i nazikçe ortaya çıkarır.
import { resolveEnvironment, resolveNgxLoggerConfig, resolveSomethingElse } from './environment-resolvers';
import { LoggerConfig } from 'ngx-logger';
@NgModule({
modules: [
SomeModule.forRoot(resolveSomethingElse)
],
providers:[
{
provide: ENVIRONMENT,
useFactory: resolveEnvironment
},
{
provide: LoggerConfig,
useFactory: resolveNgxLoggerConfig
}
]
})
export class AppModule
Ek
API URL'lerimin oluşturulmasını nasıl çözdüm?
Her url'nin bir yorum aracılığıyla ne yaptığını anlayabilmek ve TypeScript'in javascript'e (IMO) kıyasla en büyük gücü bu olduğundan, yazım denetimi yapmak istedim. Ayrıca, diğer geliştiricilerin yeni uç noktalar ve olabildiğince sorunsuz api'ler ekleyebileceği bir deneyim oluşturmak istedim.
Ortamı (dev, test, stage, prod, "" vb.) Alan bir sınıf oluşturdum ve bu değeri, görevi her API koleksiyonu için temel url oluşturmak olan bir dizi sınıfa [1-N] geçirdim . Her ApiCollection, her API koleksiyonu için temel URL'yi oluşturmaktan sorumludur. Kendi API'lerimiz, bir satıcının API'ları veya hatta bir harici bağlantı olabilir. Bu sınıf, oluşturulan temel url'yi içerdiği sonraki her api'ye iletir. Çıplak kemik örneği görmek için aşağıdaki kodu okuyun. Bir kez kurulduktan sonra, başka bir geliştiricinin bir Api sınıfına başka hiçbir şeye dokunmadan başka bir uç nokta eklemesi çok basittir.
TLDR; bellek optimizasyonu için temel OOP ilkeleri ve tembel alıcılar
@Injectable({
providedIn: 'root'
})
export class ApiConfig {
public apis: Apis;
constructor(@Inject(ENVIRONMENT) private environment: string) {
this.apis = new Apis(environment);
}
}
export class Apis {
readonly microservices: MicroserviceApiCollection;
constructor(environment: string) {
this.microservices = new MicroserviceApiCollection(environment);
}
}
export abstract class ApiCollection {
protected domain: any;
constructor(environment: string) {
const domain = this.resolveDomain(environment);
Object.defineProperty(ApiCollection.prototype, 'domain', {
get() {
Object.defineProperty(this, 'domain', { value: domain });
return this.domain;
},
configurable: true
});
}
}
export class MicroserviceApiCollection extends ApiCollection {
public member: MemberApi;
constructor(environment) {
super(environment);
this.member = new MemberApi(this.domain);
}
resolveDomain(environment: string): string {
return `https://subdomain${environment}.actualdomain.com/`;
}
}
export class Api {
readonly base: any;
constructor(baseUrl: string) {
Object.defineProperty(this, 'base', {
get() {
Object.defineProperty(this, 'base',
{ value: baseUrl, configurable: true});
return this.base;
},
enumerable: false,
configurable: true
});
}
attachProperty(name: string, value: any, enumerable?: boolean) {
Object.defineProperty(this, name,
{ value, writable: false, configurable: true, enumerable: enumerable || true });
}
}
export class MemberApi extends Api {
get MemberInfo() {
this.attachProperty("MemberInfo", `${this.base}basic-info`);
return this.MemberInfo;
}
constructor(baseUrl: string) {
super(baseUrl + "member/api/");
}
}