हमारे पास यह समस्या वर्षों पहले थी जब मैं इसमें शामिल हुआ था और इसमें एक समाधान था जो उपयोगकर्ता और पर्यावरण की जानकारी के लिए स्थानीय भंडारण का उपयोग करता था। कोणीय 1.0 दिन सटीक होना चाहिए। हम पूर्व में गतिशील रूप से रनटाइम पर एक js फ़ाइल बना रहे थे जो तब उत्पन्न एपीआई यूआरएल को एक वैश्विक चर में रखेगा। हम इन दिनों थोड़ा अधिक OOP से प्रेरित हैं और किसी भी चीज़ के लिए स्थानीय भंडारण का उपयोग नहीं करते हैं।
मैंने पर्यावरण और एपि url निर्माण के निर्धारण के लिए बेहतर समाधान तैयार किया।
यह कैसे भिन्न होता है?
जब तक config.json फ़ाइल लोड नहीं होगी तब तक ऐप लोड नहीं होगा। यह एसओसी की उच्च डिग्री बनाने के लिए कारखाने के कार्यों का उपयोग करता है। मैं इसे एक सेवा में संलग्न कर सकता था, लेकिन मैंने कभी कोई कारण नहीं देखा जब फ़ाइल के विभिन्न वर्गों के बीच एकमात्र समानता यह है कि वे फ़ाइल में एक साथ मौजूद हैं। फैक्ट्री फ़ंक्शन होने से मुझे फ़ंक्शन को सीधे मॉड्यूल में पास करने की अनुमति मिलती है यदि यह फ़ंक्शन को स्वीकार करने में सक्षम है। अंत में, मेरे पास एक आसान समय है जब इंजेक्शनटोकेंस की स्थापना की जाए, जब फैक्ट्री फ़ंक्शन उपयोग के लिए उपलब्ध हों।
Downsides?
यदि आप जिस मॉड्यूल को कॉन्फ़िगर करना चाहते हैं, इस सेटअप (और अधिकांश उत्तरों) का उपयोग करके आप भाग्य से बाहर हैं, तो कारखाने के फ़ंक्शन को या तो forRoot () या forChild () में पारित करने की अनुमति नहीं देता है, और इसके लिए कोई अन्य तरीका नहीं है फ़ैक्टरी फ़ंक्शन का उपयोग करके पैकेज को कॉन्फ़िगर करें।
अनुदेश
- एक json फ़ाइल को पुनः प्राप्त करने के लिए लाने के लिए, मैं विंडो में ऑब्जेक्ट को स्टोर करता हूं और एक कस्टम इवेंट बढ़ाता हूं। - whatwg-fet स्थापित करने के लिए याद रखें और IE संगतता के लिए इसे अपने polyfills.ts में जोड़ें
- एक ईवेंट श्रोता को कस्टम ईवेंट के लिए सुनें।
- ईवेंट श्रोता को ईवेंट प्राप्त होता है, विंडो से ऑब्जेक्ट को एक ऑब्जर्व करने योग्य पास करने के लिए पुनः प्राप्त करता है, और यह स्पष्ट करता है कि विंडो में क्या संग्रहीत किया गया था।
- बूटस्ट्रैप कोणीय
- यह वह जगह है जहाँ मेरा समाधान वास्तव में भिन्न होता है -
- एक इंटरफ़ेस बनाने वाली फ़ाइल बनाएँ जिसकी संरचना आपके config.json का प्रतिनिधित्व करती है - यह वास्तव में प्रकार की स्थिरता के साथ मदद करता है और कोड के अगले भाग के लिए एक प्रकार की आवश्यकता होती है, और जब आप जानते हैं कि आप कुछ और अधिक निर्दिष्ट कर सकते हैं
{}या निर्दिष्ट नहीं करते anyहैं
- BehaviorSubject बनाएं कि आप चरण 3 में पार्स किए गए जोंस फ़ाइल को पास करेंगे।
- SOC को बनाए रखने के लिए अपने कॉन्फ़िगरेशन के विभिन्न अनुभागों को संदर्भित करने के लिए फ़ैक्टरी फ़ंक्शन का उपयोग करें
- अपने कारखाने के कार्यों के परिणाम की आवश्यकता वाले प्रदाताओं के लिए InjectionTokens बनाएं
- और / या -
- कारखाने के कार्यों को सीधे अपने forRoot () या forChild () विधियों में से किसी एक फ़ंक्शन को स्वीकार करने में सक्षम मॉड्यूल में पास करें।
- मुख्य
मैं विंडो की जांच करता हूं ["पर्यावरण"] एक घटना श्रोता को बनाने से पहले आबाद नहीं किया जाता है ताकि समाधान के possiblilty को अनुमति दी जा सके जहां खिड़की ["पर्यावरण"] कुछ अन्य माध्यमों से पॉपअप हो जाती है।
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));
});
}
--- पर्यावरण- resolvers.ts
मैं अतिरेक के लिए खिड़की ["पर्यावरण"] का उपयोग करते हुए BehaviorSubject के लिए एक मान प्रदान करता हूं। आप एक ऐसा समाधान तैयार कर सकते हैं, जहां आपका कॉन्फिगरेशन पहले से ही लोड हो और विंडो ["एनवायरनमेंट"] पहले से ही पॉपुलर हो, जब तक कि आपका कोई भी Angular का ऐप कोड रन नहीं करता, जिसमें main.ts कोड शामिल है
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) {
// case statements for determining whether this is dev, test, stage, or prod
}
return resolvedEnvironment;
}
export function resolveNgxLoggerConfig() {
return configurationSubject.getValue().logging;
}
- app.module.ts - आसान समझ के लिए नीचे स्ट्रिप किया गया
मजेदार तथ्य! NGXLogger के पुराने संस्करणों के लिए आपको LoggerModule.forRoot () में किसी ऑब्जेक्ट को पास करने की आवश्यकता है। वास्तव में, लकड़हारा अभी भी करता है! NGXLogger कृपया LoggerConfig को उजागर करता है जिसे आप सेटअप के लिए फ़ैक्टरी फ़ंक्शन का उपयोग करने की अनुमति देकर ओवरराइड कर सकते हैं।
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
परिशिष्ट
मैंने अपने एपीआई यूआरएल के निर्माण को कैसे हल किया?
मैं यह समझना चाहता था कि प्रत्येक url ने एक टिप्पणी के माध्यम से क्या किया और टाइपकास्ट करना चाहता था क्योंकि वह टाइपस्क्रिप्ट की सबसे बड़ी ताकत जावास्क्रिप्ट (IMO) की तुलना में है। मैं नए समापन बिंदु जोड़ने के लिए अन्य देवताओं के लिए एक अनुभव बनाना चाहता था, और एपिस जो संभव के रूप में सहज था।
मैंने एक वर्ग बनाया जो पर्यावरण (देव, परीक्षण, मंच, ठेस, "", और आदि) में लेता है और इस मूल्य को कक्षा की एक श्रृंखला [1-N] को पारित करता है जिसका काम प्रत्येक एपीआई संग्रह के लिए आधार यूआरएल बनाना है । प्रत्येक ApiCollection एपीआई के प्रत्येक संग्रह के लिए बेस यूआरएल बनाने के लिए जिम्मेदार है। हमारे अपने एपीआई, एक विक्रेता के एपीआई, या यहां तक कि एक बाहरी लिंक हो सकता है। वह वर्ग निर्मित आधार यूआरएल को प्रत्येक बाद के एपी में सम्मिलित करेगा। नंगे हड्डियों का उदाहरण देखने के लिए नीचे दिए गए कोड को पढ़ें। एक बार सेटअप करने के बाद, किसी अन्य देवता के लिए बहुत आसान है कि वह किसी अन्य चीज को छूने के बिना एक और वर्ग के लिए एक एंडपॉइंट जोड़ सकता है।
TLDR; स्मृति अनुकूलन के लिए बुनियादी ओओपी सिद्धांत और आलसी गेटर्स
@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/");
}
}