Programing

백엔드에서 렌더링 된 매개 변수를 angular2 부트 스트랩 메서드로 전달하는 방법

lottogame 2020. 11. 8. 09:11
반응형

백엔드에서 렌더링 된 매개 변수를 angular2 부트 스트랩 메서드로 전달하는 방법


백엔드에서 렌더링 된 인수를 angular2 부트 스트랩 메서드로 전달하는 방법이 있습니까? 백엔드에서 제공된 값으로 BaseRequestOptions사용하여 모든 요청에 ​​대해 http 헤더를 설정하고 싶습니다 . main.ts파일은 다음과 같습니다.

import { bootstrap } from '@angular/platform-browser-dynamic';
import { AppComponent } from "./app.component.ts";

bootstrap(AppComponent);

이 인수를 루트 구성 요소 ( https://stackoverflow.com/a/35553650/3455681 ) 에 전달하는 방법을 찾았 지만 bootstrap메서드를 실행할 때 필요합니다 ... 아이디어가 있습니까?

편집하다:

webpack.config.js 콘텐츠 :

module.exports = {
  entry: {
    app: "./Scripts/app/main.ts"
  },

  output: {
    filename: "./Scripts/build/[name].js"
  },

  resolve: {
    extensions: ["", ".ts", ".js"]
  },

  module: {
    loaders: [
      {
        test: /\.ts$/,
        loader: 'ts-loader'
      }
    ]
  }
};

update2

플 런커 예

AoT 업데이트

AoT를 사용하려면 공장 폐쇄를 제거해야합니다.

function loadContext(context: ContextService) {
  return () => context.load();
}

@NgModule({
  ...
  providers: [ ..., ContextService, { provide: APP_INITIALIZER, useFactory: loadContext, deps: [ContextService], multi: true } ],

참조 https://github.com/angular/angular/issues/11262

RC.6 및 2.0.0 최종 예제 업데이트

function configServiceFactory (config: ConfigService) {
  return () => config.load();
}

@NgModule({
    declarations: [AppComponent],
    imports: [BrowserModule,
        routes,
        FormsModule,
        HttpModule],
    providers: [AuthService,
        Title,
        appRoutingProviders,
        ConfigService,
        { provide: APP_INITIALIZER,
          useFactory: configServiceFactory
          deps: [ConfigService], 
          multi: true }
    ],
    bootstrap: [AppComponent]
})
export class AppModule { }

초기화가 완료 될 때까지 기다릴 필요가 없으면`class AppModule {}의 생성자를 사용할 수도 있습니다.

class AppModule {
  constructor(/*inject required dependencies */) {...} 
}

힌트 (순환 종속성)

예를 들어 라우터를 삽입하면 순환 종속성이 발생할 수 있습니다. 이 문제를 해결하려면 다음을 Injector통해 종속성을 주입 하고 가져옵니다.

this.myDep = injector.get(MyDependency);

다음 MyDependency과 같이 직접 주입하는 대신 :

@Injectable()
export class ConfigService {
  private router:Router;
  constructor(/*private router:Router*/ injector:Injector) {
    setTimeout(() => this.router = injector.get(Router));
  }
}

최신 정보

이것은 RC.5에서 동일하게 작동해야하지만 대신에 providers: [...]루트 모듈 의 공급자를 추가하십시오.bootstrap(...)

(아직 테스트하지 않았습니다).

최신 정보

Angular 내에서 완전히 수행하는 흥미로운 접근 방식은 여기에 설명되어 있습니다 https://github.com/angular/angular/issues/9047#issuecomment-224075188

APP_INITIALIZER앱이 초기화 될 때 함수를 실행할 함수를 사용 하고 함수가 promise를 반환하면 제공하는 것을 지연시킬 수 있습니다. 즉, 앱이 지연 시간없이 초기화 될 수 있으며 기존 서비스 및 프레임 워크 기능을 사용할 수도 있습니다.

예를 들어 사이트 정보가 제공되는 도메인 이름에 의존하는 다중 테넌트 솔루션이 있다고 가정합니다. 이것은 [name] .letterpress.com 또는 전체 호스트 이름과 일치하는 사용자 지정 도메인 일 수 있습니다. 을 사용하여 이것이 약속 뒤에 있다는 사실을 숨길 수 있습니다 APP_INITIALIZER.

부트 스트랩에서 :

{provide: APP_INITIALIZER, useFactory: (sites:SitesService) => () => sites.load(), deps:[SitesService, HTTP_PROVIDERS], multi: true}),

sites.service.ts :

@Injectable()
export class SitesService {
  public current:Site;

  constructor(private http:Http, private config:Config) { }

  load():Promise<Site> {
    var url:string;
    var pos = location.hostname.lastIndexOf(this.config.rootDomain);
    var url = (pos === -1)
      ? this.config.apiEndpoint + '/sites?host=' + location.hostname
      : this.config.apiEndpoint + '/sites/' + location.hostname.substr(0, pos);
    var promise = this.http.get(url).map(res => res.json()).toPromise();
    promise.then(site => this.current = site);
    return promise;
  }

참고 : config사용자 지정 구성 클래스입니다. rootDomain'.letterpress.com'이 예를 들어 물건이 좋아하는 수 것입니다 aptaincodeman.letterpress.com.

이제 모든 구성 요소 및 기타 서비스를 여기에 Site삽입 .current하고 앱 내에서 약속을 기다릴 필요없이 구체적으로 채워진 개체가 될 속성을 사용할 수 있습니다.

이 접근 방식은 큰 Angular 번들이로드 될 때까지 기다린 다음 부트 스트랩이 시작되기 전에 또 다른 http 요청을 기다리는 경우 눈에 띄는 시작 지연 시간을 줄이는 것처럼 보였습니다.

실물

Angulars 종속성 주입을 사용하여 전달할 수 있습니다.

var headers = ... // get the headers from the server

bootstrap(AppComponent, [{provide: 'headers', useValue: headers})]);
class SomeComponentOrService {
   constructor(@Inject('headers') private headers) {}
}

또는 BaseRequestOptions직접 준비된 제공

class MyRequestOptions extends BaseRequestOptions {
  constructor (private headers) {
    super();
  }
} 

var values = ... // get the headers from the server
var headers = new MyRequestOptions(values);

bootstrap(AppComponent, [{provide: BaseRequestOptions, useValue: headers})]);

Angular2 최종 릴리스에서는 APP_INITIALIZER 공급자를 사용하여 원하는 것을 얻을 수 있습니다.

완전한 예제로 Gist를 작성했습니다 : https://gist.github.com/fernandohu/122e88c3bcd210bbe41c608c36306db9

요점 예제는 JSON 파일에서 읽는 것이지만 REST 엔드 포인트에서 읽도록 쉽게 변경할 수 있습니다.

필요한 것은 기본적으로 다음과 같습니다.

a) 기존 모듈 파일에 APP_INITIALIZER를 설정합니다.

import { APP_INITIALIZER } from '@angular/core';
import { BackendRequestClass } from './backend.request';
import { HttpModule } from '@angular/http';

...

@NgModule({
    imports: [
        ...
        HttpModule
    ],
    ...
    providers: [
        ...
        ...
        BackendRequestClass,
        { provide: APP_INITIALIZER, useFactory: (config: BackendRequestClass) => () => config.load(), deps: [BackendRequestClass], multi: true }
    ],
    ...
});

이 라인은 애플리케이션이 시작되기 전에 BackendRequestClass 클래스에서 load () 메서드를 호출합니다.

라이브러리에 내장 된 angular2를 사용하여 백엔드에 http 호출을하려면 "imports"섹션에서 "HttpModule"을 설정해야합니다.

b) 클래스를 만들고 파일 이름을 "backend.request.ts"로 지정합니다.

import { Inject, Injectable } from '@angular/core';
import { Http } from '@angular/http';
import { Observable } from 'rxjs/Rx';

@Injectable()
export class BackendRequestClass {

    private result: Object = null;

    constructor(private http: Http) {

    }

    public getResult() {
        return this.result;
    }

    public load() {
        return new Promise((resolve, reject) => {
            this.http.get('http://address/of/your/backend/endpoint').map( res => res.json() ).catch((error: any):any => {
                reject(false);
                return Observable.throw(error.json().error || 'Server error');
            }).subscribe( (callResult) => {
                this.result = callResult;
                resolve(true);
            });

        });
    }
}

c) 백엔드 호출의 내용을 읽으려면 선택한 클래스에 BackendRequestClass를 주입하고 getResult ()를 호출하기 만하면됩니다. 예:

import { BackendRequestClass } from './backend.request';

export class AnyClass {
    constructor(private backendRequest: BackendRequestClass) {
        // note that BackendRequestClass is injected into a private property of AnyClass
    }

    anyMethod() {
        this.backendRequest.getResult(); // This should return the data you want
    }
}

문제가 해결되면 알려주세요.


진입 점에서 부트 스트랩 자체를 호출하는 대신 작업을 수행하는 함수를 만들고 내보낼 수 있습니다.

export function doBootstrap(data: any) {
    platformBrowserDynamic([{provide: Params, useValue: new Params(data)}])
        .bootstrapModule(AppModule)
        .catch(err => console.error(err));
}

설정 (webpack / SystemJS)에 따라이 함수를 전역 개체에 배치 할 수도 있습니다. 또한 AOT와 호환됩니다.

This has the added benefit to delay the bootstrap, whenit makes sense. For instance, when you retrieve this user data as an AJAX call after the user fills out a form. Just call the exported bootstrap function with this data.


The only way to do that is to provide these values when defining your providers:

bootstrap(AppComponent, [
  provide(RequestOptions, { useFactory: () => {
    return new CustomRequestOptions(/* parameters here */);
  });
]);

Then you can use these parameters in your CustomRequestOptions class:

export class AppRequestOptions extends BaseRequestOptions {
  constructor(parameters) {
    this.parameters = parameters;
  }
}

If you get these parameters from an AJAX request, you need to bootstrap asynchronously this way:

var appProviders = [ HTTP_PROVIDERS ]

var app = platform(BROWSER_PROVIDERS)
  .application([BROWSER_APP_PROVIDERS, appProviders]);

var http = app.injector.get(Http);
http.get('http://.../some path').flatMap((parameters) => {
  return app.bootstrap(appComponentType, [
    provide(RequestOptions, { useFactory: () => {
      return new CustomRequestOptions(/* parameters here */);
    }})
  ]);
}).toPromise();

See this question:

Edit

Since you have your data in the HTML you could use the following.

You can import a function and call it with parameters.

Here is a sample of the main module that bootstraps your application:

import {bootstrap} from '...';
import {provide} from '...';
import {AppComponent} from '...';

export function main(params) {
  bootstrap(AppComponent, [
    provide(RequestOptions, { useFactory: () => {
      return new CustomRequestOptions(params);
    });
  ]);
}

Then you can import it from your HTML main page like this:

<script>
  var params = {"token": "@User.Token", "xxx": "@User.Yyy"};
  System.import('app/main').then((module) => {
    module.main(params);
  });
</script>

이 질문을 참조하십시오 : _layout.cshtml에서 Angular에 상수 값 전달 .

참고 URL : https://stackoverflow.com/questions/37611549/how-to-pass-parameters-rendered-from-backend-to-angular2-bootstrap-method

반응형