2016-10-19 9 views
0

私は現在、職場で開発したアプリケーションを再作成してangular2を学習しています。アプリの一部が複数のhttp呼び出しを行う必要があります。各コールは、前のコールの結果に依存します。前の呼び出しの結果からIDを使用するように2番目、3番目の呼び出しなどをしたい。Angular2 - 互いに依存する複数のHTTPリクエスト

import {Component, OnInit} from '@angular/core'; 
import {VillageService} from './village.service'; 

@Component({ 
    selector: 'village', 
    templateUrl: 'app/village/village.component.html', 
    styleUrls: ['assets/stylesheets/styles.css'], 
    providers: [VillageService] 
}) 

export class VillageComponent implements OnInit { 
    villages = []; 
    workAreas = []; 
    shifts = []; 
    roles = []; 

    constructor(private _villageService: VillageService){ 
    } 

    ngOnInit() { 
     this._villageService.GetAllVillages() 
     .subscribe(res => { 
      this.villages = res; 
     }, 
     null, 
     () => { 
      //Get all work areas for each village 
      for(let i = 0; i < this.villages.length; i++){ 
      this._villageService.GetAllWorkAreas(this.villages[i].VillageId) 
       .subscribe(res => { 
        this.workAreas = res; 
       }, 
       null, 
       () => { 
        //Get all shifts for each work area 
        for(let j = 0; j < this.workAreas.length; j++){ 
         this._villageService.GetAllShifts(this.workAreas[j].WorkAreaId) 
         .subscribe(res => { 
          this.shifts = res; 
         }, 
         null, 
         () => { 
          //Get all roles for each shift 
          for(let k = 0; k < this.shifts.length; k++){ 
           this._villageService.GetAllRoles(this.shifts[k].ShiftId) 
           .subscribe(res => { 
            this.roles = res; 
           }, 
           null, 
           () => { 
            this.shifts[k].roles = this.roles; 
           }); 
          } 
          this.workAreas[j].shifts = this.shifts; 
         }); 
        } 
        this.villages[i].workAreas = this.workAreas; 
        console.log(this.villages[i]); 
       }); 
      } 
     }); 
    } 
} 

サービス:

import { Injectable }  from '@angular/core'; 
import { Http, Response } from '@angular/http'; 
import { Observable } from 'rxjs'; 
import 'rxjs/add/operator/map'; 

@Injectable() 
export class VillageService { 
    private _baseUrl = "{BASE_URL_ADDRESS_GOES_HERE}"; 

    constructor(private _http: Http){} 

    GetAllVillages() { 
     return this._http.get(this._baseUrl + "village/All").map(res =>  res.json()); 
    } 

    GetAllWorkAreas(villageId) { 
     return this._http.get(this._baseUrl + "WorkArea/All/" + villageId).map(res => res.json()); 
    } 

    GetAllShifts(workAreaId) { 
     return this._http.get(this._baseUrl + "Shift/All/" + workAreaId).map(res => res.json()); 
    } 

    GetAllRoles(shiftId) { 
     return this._http.get(this._baseUrl + "Role/All/" + shiftId).map(res => res.json()); 
    } 
} 

コードが部分的に機能

コンポーネントを次のように

マイ部品コードとサービスコードがあります。私は各村にそれぞれの職場を持っています。しかし、最後の村と作業場だけがそのシフトと役割を持っています。私の論理には何か間違っていると推測されますが、それが何かを見ることはできません。私も複数のループを行うのが好きではありませんが、これを行う別の方法を考えることができませんでした。

これをより良くする方法を知っている人はいますか?私は何が起こっているか見るためにデバッグを試みましたが、ループ地獄に巻き込まれ続けます。

ありがとうございます。どんな助けもありがとうございます。

答えて

3

呼び出しの結果が別の呼び出しに使用されている構造体(call1 => call2 => call3)は、コードの詳細を調べることなく、演算子を使用する必要があります。mergeMap(flatmap rxjsで)。これはちょっとこのように見えます。

this._villageService.GetAllVillages() 
    .flatMap(
     (response) => { 
     // take from the response what you want and use it for the next call 
     this._villageService.GetAllWorkAreas(//pass the thing from your previous response here) 
     } 
    ) 
    .flatMap(
     .... 
    ) 
    .subscribe(...) 

このflatMapは、すべての従属呼び出しで必要なだけ繰り返します。

flatMapの機能は、すべての値に対して関数を実行し、その関数が観測値を返すことを期待しています。カバーの下で、それはその観測可能なものを購読し、それが値を持つと、それを次のフラットマップに送るでしょう。

まず、すべての村を手に入れます。この値を持つと、最初のflatMapに送信されます。最初のものは別の要求を行います。その要求が完了すると、その結果は次のflatMapなどになります。

+0

ありがとうございました。私はflatMapについて少しは読んだことがありますが、動作させる方法を正確に理解できませんでした。私はチャンスがあるときに遊びに行くだろう。 flatMapは各村に作業領域のコレクションを持たせることができ、各作業領域にはシフトのコレクションなどがありますか?それを動作させるためにすばやく行ったとき、レスポンスのIDを1つ追加するように見えましたが、コレクション全体ではありませんでした。 –

+0

作業領域のリストがあり、それぞれにシフトのコレクションがあり、それは上記の例では機能しません。私が疑問に思っているのは、すべての情報を提供する休憩のエンドポイントを提供してみませんか?別のx番号の要求を行うx個の要求を実行することは実際には効率的ではありません。その場合に必要なものすべてを返す単一のエンドポイントを作成する方がよいでしょう。 – KwintenP

0

これは変数iとjとasync jsのスコープに問題があります。サブスクリプションがトリガーされると、iまたはjはすでにループの終わりにあります。だからこそ、最後の村や仕事場の結果しか得られないのです。インデックス関数を直接関数にラップしようとする。

for(let i = 0; i < this.villages.length; i++){ 
    (function(i) { 
    your async code... 

    })(i); 
} 
+0

ありがとうございます。私が読んだほとんどの場所がこのルートを示唆しているので、上記のflatMapの例を最初に取り上げてみましょう。私はそれを働かせることができない場合は、私はあなたの提案を与えるでしょう。 –

関連する問題