2016-09-27 12 views
10

thisでお勧めしますように私はAPP_INITIALIZERを使用していますが、私のサービスは約束を返していますが、常に解決するのを待つとは限りません。サービスはダウンロードされたオブジェクトをログに記録します。Angular2 APP_INITIALIZERに一貫性がありません

このデータを読み込む前にアプリが何もしないようにする必要があります。

import { NgModule, APP_INITIALIZER } from '@angular/core'; 
import { Http, HttpModule, JsonpModule } from '@angular/http'; 
import { UserService } from '../services/user.service'; 

<...> 
@NgModule({ 
    imports: [ 
    BrowserModule, 
    HttpModule, 
    FormsModule, 
    JsonpModule, 
    routing 
    ], 
    declarations: [ 
    AppComponent, 
    <...> 
    ], 
    providers: [ 
    <...> 
    UserService, 
    {provide: APP_INITIALIZER, 
     useFactory: (userServ: UserService) =>() => userServ.getUser(), 
     deps: [UserService, Http], 
     multi: true 
    } 
    ], 
    bootstrap: [AppComponent] 

user.service.ts

@Injectable() 
export class UserService { 

    public user: User; 
    constructor(private http: Http) { } 

    getUser(): Promise<User> { 
     console.log('get user called'); 
     var observable= this.http.get('/auth/getuser', { headers: getHeaders() }) 
      .map(extractData); 

     observable.subscribe(user => {this.user = user; 
      console.log(this.user)}); 
     return observable.toPromise(); 
    } 
} 
+0

それはOKに見えます。使用しているパッケージのバージョンを明記してください。問題をフィドル/プルンクとして再現できますか? – estus

+0

なぜ私は未定義の値を持つログを取得しているのか分かりませんが、observableで 'toPromise()'と 'subscribe()'の両方を使うと、 '/ auth/getuser'を二度呼びます。 –

答えて

16

は、次のコードを試してみてください。後期

+0

ちょっと、私はそれをかなり前から実際に作っていましたが、これはまさに私がやったことです。 – LLL

+0

私はobservablesがオブジェクトの最初の変更(すべての応答データを含まない)でトリガされると思っていますが、タスク全体が完了したときに約束がトリガされます。私にもこの問題が解決されたので投票しました。 –

+0

@DesislavKamenov、いいえ、それは「設計による」だ:)このスレッドを読む:https://github.com/angular/angular/issues/9047 – rook

1

app.module.tsは、コンフィグ設定も動作するはずロードの約束を使用してCanActivateクラスを使用してルートを守ります。

ちょうど約束

getAppSettings(): Promise<any> { 
     var observable = this.http.get(this.ApiUrl, { headers: this.headers }) 
      .map((response: Response) => { 
       var res = response.json(); 
       return res; 
      }); 

     observable.subscribe(config => { 
     this.config= config; 
     console.log(this.config) 
     }); 
     return observable.toPromise(); 
    } 

を返す1と以下のようにCanActivateガードのような機能をappSettings.serviceを使用します。

import { Injectable } from '@angular/core'; 
import { Router, CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router'; 
import { AppSettingsService } from './appsettings.service'; 

@Injectable() 
export class CanActivateViaAuthGuard implements CanActivate { 

//router: Router 
    constructor(private appSettingsService: AppSettingsService) 
    { 
    } 

    canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) { 
       return this.appSettingsService.getAppSettings().then(() => { 
    return true }); 
    } 
} 

これは、あなたの設定が可能な場合であることを確認します対応するコンポーネントが構築される。 (APP_INITIALIZERを使用してコンストラクタが呼び出されるのを制限しなかったので、このテクニカルを使用しなければなりませんでした)また、エクスポートのすべてのコンポーネントをエクスポートする必要はありません:

ルートとコンストラクタが呼び出される前にAbcComponentのコンストラクタが呼び出される前のAppSettingsの初期化が起こるはずの設定がロードされていることを確認し、

path: 'abc', 
component: AbcComponent, 
canActivate: [CanActivateViaAuthGuard] 

ルート定義のパスに通常のcanActivateオプションを使用してください、これはテストされ、中に動作しています角2.0.1

私はそれが正しい場所であるかどうかわかりませんoadの設定が目的を果たしているようです。

2

私はこの問題はあなたが観測可能なものを購読しているために起こったと思います。 これは私がtoPromise()が必要であるかどうかわからないんだけど

@Injectable() 
export class UserService { 

    public user: User; 
    constructor(private http: Http) { } 

    getUser(): Promise<User> { 
     console.log('get user called'); 
     return observable= this.http.get('/auth/getuser', { headers: getHeaders() }) 
      .map(extractData) 
      .do(user => { 
       this.user = user; 
       console.log(this.user) 
      }) 
      .toPromise(); 
    } 
} 

を動作するはずです。私はそれがObservableと同様に働くと期待しています。私は同じ問題に直面し、そして約束の代わりに、観察可能な私のためのトリックをしたを使用していた

getUser(): Promise<User> { 
    console.log('get user called'); 
    var promise = this.http.get('/auth/getuser', {headers: getHeaders()}) 
     .map(extractData) 
     .toPromise(); 
    promise.then(user => { 
     this.user = user; 
     console.log(this.user); 
    }); 
    return promise; 
} 

0

ていますが、観測を(私は)戻って、あなたのサービスクラスを維持したい場合は、お使いのアプリケーションモジュールクラスでこのようにそれを呼び出す:

function authenticationFactory(service: AuthenticationService) { 
    console.log("calling login"); 
    //Call auth service login to get JWT info and startup data. 
    //Also convert from an Observable to a Promise to work with APP_INITIALIZER. 
    return() => service.login().toPromise().then(/*do nothing here*/); 
} 

NgModule Metadata stuff... 

providers: [ 
    ... 
    AuthenticationService, 
    { 
     provide: APP_INITIALIZER, 
     useFactory: authenticationFactory, 
     deps: [AuthenticationService], 
     multi: true 
    }, 
    ... 
    ], 
関連する問題