2016-05-14 6 views
4

私はAngular2を試しており、チュートリアルに従っています。Angular2 - OnInit:Serviceのsubscribe関数から返された値がComponentフィールドに割り当てられません。

私は現在、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メソッド内でデータを記録できるので、サービスメソッド呼び出しからデータがコンポーネントに返されることはわかります。私が最初にgetUsersを呼び出すが、奇妙なことは、私のngOnInit上にconsole.logの呼び出しは、最初に私のgetUsersメソッド内console.logs前に私のdevのコンソールに印刷されている:

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

Devのコンソールのスクリーンショット:

答えて

7

これはthis.getUsers()、その後this.userService.getUsers().subscribe(...)のみスケジュールサーバに要求を行うための呼び出しです。最終的にサーバーからの応答が到着すると(console.log('ngOnit after getUsers() ' + this.users);がすでに実行されてからサーバーにコールされる前に)、subscribe()に渡された関数が実行されます。

これは、あなたが欲しいものを行う必要があります。getUsers()

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

は私の代わりにサブスクライブのmap()使うので、我々は、応答が到着したときに実行されるコードを取得することができるようにするために、後に購読することができます。

はその後 ngOnInit()に、我々は(それ以外 http.get()実行されないだろうだろう、 subscribe()必要です) subscribe()を使用し、応答が到着したときに私たちが望むコードが実行されるように渡します。

また、function()() =>に変更しました。この方法でthisは、次のコードブロック() => { ... }の中で動作します。

は、そうでない場合は、これらの事業者はrecoginzedされることはありません

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

を追加することを忘れないでください。

+0

これを試してみていただきありがとうございます。ngOnInitコンソールログの呼び出し内に値が表示されますが、テンプレートのユーザープロパティを参照すると、未定義の値が取得されます。サービス取得メソッド呼び出しから返されたオブザーバブルに暗黙的にサブスクライブする代わりに非同期機能を使用することは有効です。私はまだAngularのチュートリアルでうまくいけば、上記がうまくいかない理由は分かりません。 –

+1

エラーは、Angularが 'ngOnInit()'の前に値をバインドしようとしているために発生します。 '{{users.xxx}} 'の代わりに' {{users?.xxx}} 'を使用してエラーを取得しないでください。 –

+0

それは私の問題を修正しました。ありがとう! –

関連する問題