1. ホーム
  2. javascript

[解決済み] angularでObservable/http/asyncの呼び出しから応答を返すにはどうすればよいですか?

2022-07-28 15:35:10

質問

サーバーにhttpリクエストを行い、データを取得するobservableを返すサービスがあります。このデータを使用したいのですが、いつも undefined . 何が問題なのでしょうか?

サービス :

@Injectable()
export class EventService {

  constructor(private http: Http) { }

  getEventList(): Observable<any>{
    let headers = new Headers({ 'Content-Type': 'application/json' });
    let options = new RequestOptions({ headers: headers });

    return this.http.get("http://localhost:9999/events/get", options)
                .map((res)=> res.json())
                .catch((err)=> err)
  }
}

コンポーネントです。

@Component({...})
export class EventComponent {

  myEvents: any;

  constructor( private es: EventService ) { }

  ngOnInit(){
    this.es.getEventList()
        .subscribe((response)=>{
            this.myEvents = response;
        });

    console.log(this.myEvents); //This prints undefined!
  }
}

私が調べたのは 非同期呼び出しからレスポンスを返すにはどうすればよいですか? を投稿しましたが、解決策は見つかりませんでした。

どのように解決するのですか?

理由は?

という理由は undefined になっているのは、非同期な操作をしているからです。つまり、この操作を行うには getEventList メソッドを完了させるのに時間がかかるということです (主にネットワークの速度に依存します)。

それでは、httpの呼び出しを見てみましょう。

this.es.getEventList()

で実際にhttpリクエストを行った("fire")後、そのリクエストに対応するように subscribe を使うと を待ちます。 を待つことになります。待っている間、javascriptはこのコードの下の行を実行し、もし同期的な割り当てや操作に遭遇したら、すぐにそれを実行することになります。

つまり getEventList() を購読し、レスポンスを待ちます。

console.log(this.myEvents);

の行はすぐに実行されます。そして、その値は undefined のように、サーバから応答が来る前に(あるいは、そもそも初期化したものに対して)実行されます。

するのと似ています。

ngOnInit(){
    setTimeout(()=>{
        this.myEvents = response;
    }, 5000);

    console.log(this.myEvents); //This prints undefined!
}


解答です。

<ブロッククオート

では、この問題をどのように克服すればよいのでしょうか。コールバック関数を使用します。 subscribe メソッドを使用します。なぜなら、サーバーからデータが届くと、それは subscribe の中に入って、レスポンスと一緒に表示されるからです。

ということで、コードを変更すると

this.es.getEventList()
    .subscribe((response)=>{
        this.myEvents = response;
        console.log(this.myEvents); //<-- not undefined anymore
    });

は、しばらくしてからレスポンスを表示します。


どうすればいいのでしょう。

単にログを取るだけでなく、レスポンスに対して行うべきことがたくさんあるかもしれません。これらの操作はすべてコールバックの内部で行う必要があります (コールバックの内部の subscribe 関数の中)で、データが到着したときに行います。

もう一つ挙げるとすれば、もしあなたが Promise の背景を持つ場合、その then コールバックは subscribe に対応します。


やってはいけないこと

非同期操作を同期操作に変更しようとしてはいけません (できるわけではありませんが)。非同期オペレーションがある理由の 1 つは、ユーザーがその時間内に他のことができるのに、オペレーションが完了するのを待たせないようにするためです。非同期操作の1つが完了するのに3分かかるとします。もし非同期操作がなかったら、インターフェースは3分間フリーズしてしまうでしょう。


お勧めの読み物です。

この回答のオリジナルクレジットは、次のとおりです。 非同期呼び出しから応答を返すにはどうすればよいですか?

しかし、angular2のリリースでtypescriptとobservablesが導入されたので、この回答はobservablesで非同期リクエストを処理するための基本をカバーすることを願っています。