2016-05-14 20 views
4

我正在嘗試Angular2並一直遵循他們的教程。Angular2 - OnInit:從服務'訂閱功能返回的值不會被分配給組件字段/ s

我現在有一個服務,它從一個JSON服務器獲取數據:

import { Injectable } from '@angular/core'; 
import { Http, Response } from '@angular/http'; 

import { Observable } from 'rxjs/Observable'; 

import { User } from './user'; 

@Injectable() 
export class UserService { 
    constructor(private http: Http) {} 

    private usersUrl = 'http://localhost:3000/users'; 

    getUsers(): Observable<User[]> { 
    return this.http.get(this.usersUrl) //the request won't go out until something subscribes to the observable 
        .map(this.extractData) 
        .catch(this.handleError); // pass an error message back to the component for presentation to the user but only if we can say something the user can understand and act upon 
    } 

    private extractData(response: Response) { 
    if (response.status < 200 || response.status >= 300) { 
     throw new Error('Bad response status: ' + response.status); 
    } 
    let body = response.json(); // parse JSON string into JavaScript objects 

    return body.data || { }; 
    } 

    private handleError (error: any) { 
    // In a real world app, we might send the error to remote logging infrastructure before returning/sending the error 
    let errMsg = error.message || 'Server error'; // transform the error into a user-friendly message 

    return Observable.throw(errMsg); // returns the message in a new, failed observable 
    } 

} 

而我的組件:

我的問題是,從訂閱的函數返回的數據不在getUsers()調用完成後傳遞/分配給我的Component屬性'users'。我知道數據從服務方法調用返回到組件,因爲我可以在userService()。getUsers方法內記錄數據。是,正在打印怪異的事情在我的ngOnInit的調用的console.log我的開發控制檯上第一我getUsers方法中的console.logs之前,雖然我第一次調用getUsers:

ngOnInit() { 
    this.getUsers(); 
    console.log('ngOnit after getUsers() ' + this.users); 
    } 

開發控制檯截圖:

回答

7

這是因爲this.getUsers(),然後this.userService.getUsers().subscribe(...)只安排一次通話,對服務器的請求。最終,當服務器的響應到達時(在調用服務器之前已經執行了console.log('ngOnit after getUsers() ' + this.users);),則執行傳遞給subscribe()的函數。

這應該做你想要什麼:

getUsers() { 
    return this.userService 
    .getUsers() 
    .map(
     (users) => { 
     console.log('users ' + users); 
     this.users = users; 
     console.log('this.users ' + this.users); 
     }) 
    .catch((error) => { 
     console.log('error ' + error); 
     throw error; 
     }); 
    // users => this.users = users, 
    // error => this.errorMsg = <any>error); 
    } 

    ngOnInit() { 
    this.getUsers().subscribe(_ => {; 
     console.log('ngOnit after getUsers() ' + this.users); 
    }); 
    } 

getUsers()我用map()而不是訂閱,這樣我們就可以爲了能夠得到當響應到達執行的代碼後訂閱。

然後在ngOnInit()我們使用subscribe()subscribe()是必要的,否則將http.get()將永遠不會被執行),並通過我們想要的代碼時響應到達執行。

我也將function()更改爲() =>。這種方式this工作在以下代碼塊() => { ... }內,否則它不會。

不要忘記添加

import 'rxjs/add/operator/map'; 
import 'rxjs/add/operator/catch'; 

否則這些運營商將不會被recoginzed。

+0

感謝您的迴應sir,在嘗試完成後,該值確實會打印在ngOnInit控制檯日誌調用中,但是當我引用模板中的用戶屬性時,仍然會收到未定義的值。儘管使用異步功能作爲隱式訂閱從服務get方法調用返回的Observable的替代方法。我仍然不明白爲什麼上面的代碼在Angular的教程中工作時不起作用? –

+1

錯誤是由Angular嘗試綁定'ngOnInit()'之前的值引起的。只需使用'{{users?.xxx}}'而不是'{{users.xxx}}'就不會出錯。 –

+0

這解決了我的問題先生。謝謝! –