2016-09-27 16 views
10

Tôi đang sử dụng APP_INITIALIZER như được đề xuất trong câu hỏi this, với dịch vụ của tôi trả lời lời hứa, nhưng không phải lúc nào cũng chờ nó giải quyết và tôi có thể xem bảng điều khiển thành phần của mình.đừng xác định và sau đó dịch vụ ghi nhật ký đối tượng đã tải xuống.Angular2 APP_INITIALIZER không nhất quán

Tôi cần ứng dụng không làm bất cứ điều gì trước khi dữ liệu này được tải.

app.module.ts

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

Có vẻ ok. Vui lòng nêu rõ bạn đang sử dụng phiên bản gói nào. Bạn có thể sao chép các vấn đề như là một fiddle/plunk? – estus

+0

Tôi không chắc chắn tại sao bạn nhận nhật ký với các giá trị không xác định, nhưng nếu bạn sử dụng cả 'toPromise()' và 'subscribe()' trên quan sát, bạn sẽ gọi '/ auth/getuser' hai lần.Bạn nên chuỗi cũng rxjs điều hành 'share()' ('rxjs/add/operator/share') –

Trả lời

16

Hãy thử đoạn mã sau:

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; 
} 

tôi đã phải đối mặt với cùng một vấn đề, và sử dụng một lời hứa thay vì một quan sát được đã làm các trick cho tôi.

+0

Hey, tôi đã làm cho nó làm việc khá một số thời gian trước đây thực sự, nhưng điều này là chính xác những gì tôi đã làm. – LLL

+0

Tôi nghĩ rằng các quan sát được kích hoạt tại thay đổi đầu tiên của đối tượng, không chứa tất cả dữ liệu phản hồi, trong khi các lời hứa được kích hoạt khi toàn bộ tác vụ được thực hiện. Bình chọn Up vì điều này đã giải quyết vấn đề cho tôi. –

+0

@DesislavKamenov, Không, đó là "theo thiết kế" :) Đọc chủ đề này: https://github.com/angular/angular/issues/9047 – rook

1

Guard tuyến đường của bạn với một lớp CanActivate sử dụng một Promise mà tải các thiết lập cấu hình cũng nên làm việc.

Sử dụng appSettings.service với một chức năng giống như một trở về một lời hứa

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(); 
    } 

Và bảo vệ CanActivate như sau:

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 }); 
    } 
} 

này sẽ đảm bảo rằng các thiết lập của bạn có sẵn khi các thành phần tương ứng được xây dựng. (bằng cách sử dụng APP_INITIALIZER đã không hạn chế các nhà xây dựng được gọi là, vì vậy tôi đã phải sử dụng kỹ thuật này, Ngoài ra hãy chắc chắn rằng, bạn không xuất khẩu tất cả các thành phần trong xuất khẩu: [] trong mô-đun)

Để bảo vệ các tuyến đường và đảm bảo thiết lập được nạp trước khi các nhà thầu được mời gọi, hãy sử dụng tùy chọn canActivate thông thường trong đường dẫn cho các định nghĩa đường

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

việc khởi của appSettings nên xảy ra trước khi các nhà xây dựng cho AbcComponent được gọi là, điều này được kiểm tra và làm việc tại Angular 2.0.1

Tôi không chắc liệu đó có phải là nơi thích hợp để l không oad config nhưng dường như phục vụ mục đích

2

Tôi nghĩ rằng vấn đề là do bạn đăng ký vào quan sát. Điều này sẽ hoạt động

@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(); 
    } 
} 

Tôi không chắc chắn nếu toPromise() là cần thiết. Tôi cũng hy vọng nó hoạt động với Observable.

0

muộn, nhưng nếu bạn muốn giữ lớp dịch vụ của bạn trở lại quan sát (I do), gọi nó là như thế này trong lớp ứng dụng mô-đun của bạn:

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 
    }, 
    ... 
    ], 
Các vấn đề liên quan