2017-12-18 11 views
0

私は現在、少し痛いAPIを扱っています:D APIは私のアプリケーションに必要な完全な情報を返しません。必要なすべての情報を入手してください。また、私は私の頭を丸めるために苦労しているので、それがうまく説明されていない場合は、私に知らせてください!問題の角度のある/イオン性の連鎖しているHTTP呼び出しが同期外になった

メイン詳細

は、現在のAPIの流れは少し次のようになります。

  1. は、 'グループIDの'(応答1を参照)のリストを取得します。

  2. 各グループIDについて、グループ内のグループの詳細とタイプを取得します(レスポンス2を参照)。

  3. グループの詳細を使用して、タイプごとにタイプ名を取得します(レスポンス3を参照)。

  4. すべての詳細を含む大きなツリーを構築します。

  5. 別のエンドポイントを使用して、すべてのスキルを取得し、それに応じてツリーを更新します(レスポンス4を参照)。

問題、私は非同期約束で約束で営巣約束だので、すべての同期がとれていません正しい場所に正しい値を返すしようとしたときに来る:

OメインAPIエンドポイントと例をhttps://esi.tech.ccp.is/latest/に見つけることができます。

私の現在のコードは、以下のように少し見えます(呼び出された順に関数をリストしようとしました)。グループのリストが返された

  • 問題は、私はポイントを見つける必要があり、です。

  • 各グループについて、含まれるタイプが返されました。

  • skillTreeオブジェクトには、以下の形式の新しいプロパティが追加されています。

スキルツリー目的:

skillTree = { 
    "groupName": [ 
     "skillID": { 
      "level": 0; 
     }, 
     "skill2ID": { 
      "level": 0; 
     },... 
    ], 
    "group2Name": [ 
     "skillID" { 
      "level": 0; 
     },... 
    ],... 
}; 

タブスキル-all.ts(メイン関数を呼び出します):

 eveESI.buildSkillTree().then(() => { 
      // Need to add names to all skills in tree... 
      console.log('Completed skill tree:'); 
      console.log(eveESI.skillTree); 
     }).catch((error) => { 
      // Do error handling... 
     }); 

eveESIプロバイダ - buildSkillTree():

 buildSkillTree(){ 
     return new Promise((resolve, reject) => { 
      this.getSkillGroups().then((groups) => { 
       console.log('Success: Fetched groups successfully!'); 
       console.log(groups); 

       // Process groups. First get group details including types. Then for each group push to main array. 
       for (var i in groups) { 
        if (groups.hasOwnProperty(i)) { 
         this.getSkillsInGroup(groups[i]).then((data) => { 

          var groupDetails = JSON.parse(data.toString()); 

          var types = groupDetails.types; 
          var name = groupDetails.name; 

          console.log('Success: Fetched types for group ' + name + ' successfully!'); 

          // Declare and build temp group object before we push it to main skill object... 
          var tempGroupObj = []; 

          // For each skill type in the group add to temporary array... 
          for (var n in types) { 
           if (types.hasOwnProperty(n)) { 
            tempGroupObj[types[n]] = {}; 
            tempGroupObj[types[n]]['level'] = 0; 
           } 
          } 

          console.log(tempGroupObj); 

          this.skillTree[name] = tempGroupObj; 

         }).then(() => { 

         }).catch((error) => { 
          // Do error handling... 
          console.log(error); 
         }); 
        } 
       } 

       resolve(); 
      }).catch((error) => { 
       // Do error handling... 
       reject(); 
      }); 
     }); 
    } 

eveESIプロバイダ - getSkillGroups() - [...を返します。】グループIDの参照応答の1:

 getSkillGroups(){ 
     return new Promise((resolve, reject) => { 
      this.http.get(this.apiRoot + 'universe/categories/16/', { }, { Authorization: 'Basic YWUxYmIzZDU4ZmRiNDk1ZDk3ZTE1ZTE0OTIyZDc0ZDk6MnpsVjNLZzVHbTh4OHY5b2lUSENYOHVXR21PYjlHd2Rqc3htQ0NHOA=='}) 
      .then(reqResponse => { 
       // Returns {} of skill groups from category... 
       var responseJSON = JSON.parse(reqResponse.data); 

       resolve(responseJSON.groups); 
      }).catch(reqError => { 
       // Error. Return error message... 
       reject(); 
      }); 
     }); 
    } 

eveESIプロバイダ - getSkillsInGroup(ID) - 戻る{...}グループの詳細の応答2参照:

getSkillsInGroup(id){ 
     return new Promise((resolve, reject) => { 
      this.http.get(this.apiRoot + 'universe/groups/' + id + '/', { }, { Authorization: 'Basic YWUxYmIzZDU4ZmRiNDk1ZDk3ZTE1ZTE0OTIyZDc0ZDk6MnpsVjNLZzVHbTh4OHY5b2lUSENYOHVXR21PYjlHd2Rqc3htQ0NHOA=='}) 
      .then(reqResponse => { 
       resolve(reqResponse.data); 
      }).catch(reqError => { 
       // Error. Return error message... 
       reject(); 
      }); 
     }); 
    } 

応答1(

{ 
    "category_id": 16, 
    "name": "Skill", 
    "published": true, 
    "groups": [ 
    255, 
    256, 
    257, 
    258, 
    266, 
    268, 
    269, 
    270, 
    272, 
    273, 
    274, 
    275, 
    278, 
    505, 
    1209, 
    1210, 
    1213, 
    1216, 
    1217, 
    1218, 
    1220, 
    1240, 
    1241, 
    1545 
    ] 
} 

レスポンス2(リターン・グループの詳細:グループIDのリスト)グループ内およびタイプ):

{ 
    "group_id": 255, 
    "name": "Gunnery", 
    "published": true, 
    "category_id": 16, 
    "types": [ 
    3300, 
    3301, 
    3302, 
    3303, 
    3304, 
    3305, 
    3306, 
    3307, 
    3308, 
    3309, 
    3310, 
    3311, 
    3312, 
    3315, 
    3316, 
    3317, 
    11082, 
    11083, 
    11084, 
    12201, 
    12202, 
    12203, 
    12204, 
    12205, 
    12206, 
    12207, 
    12208, 
    12209, 
    12210, 
    12211, 
    12212, 
    12213, 
    12214, 
    12215, 
    20327, 
    21666, 
    21667, 
    22043, 
    24563, 
    32856, 
    41403, 
    41404, 
    41405, 
    41406, 
    41407, 
    41408, 
    41537 
    ] 
} 

応答3(戻り)IDで詳細を入力します。

{ 
    "type_id": 3300, 
    "name": "Gunnery", 
    "description": "Basic turret operation skill. 2% Bonus to weapon turrets' rate of fire per skill level.", 
    "published": true, 
    "group_id": 255, 
    "market_group_id": 364, 
    "radius": 1, 
    "volume": 0.01, 
    "packaged_volume": 0.01, 
    "icon_id": 33, 
    "capacity": 0, 
    "portion_size": 1, 
    "mass": 0, 
    "dogma_attributes": [...], 
    "dogma_effects": [...] 
} 

Package.json

{ 
    "name": "name", 
    "version": "0.0.1", 
    "author": "author", 
    "homepage": "http://ionicframework.com/", 
    "private": true, 
    "scripts": { 
    "clean": "ionic-app-scripts clean", 
    "build": "ionic-app-scripts build", 
    "lint": "ionic-app-scripts lint", 
    "ionic:build": "ionic-app-scripts build", 
    "ionic:serve": "ionic-app-scripts serve" 
    }, 
    "dependencies": { 
    "@angular/common": "5.0.3", 
    "@angular/compiler": "5.0.3", 
    "@angular/compiler-cli": "5.0.3", 
    "@angular/core": "5.0.3", 
    "@angular/forms": "5.0.3", 
    "@angular/http": "5.0.3", 
    "@angular/platform-browser": "5.0.3", 
    "@angular/platform-browser-dynamic": "5.0.3", 
    "@ionic-native/browser-tab": "^4.4.2", 
    "@ionic-native/core": "4.4.0", 
    "@ionic-native/deeplinks": "^4.4.2", 
    "@ionic-native/http": "^4.4.2", 
    "@ionic-native/secure-storage": "^4.4.2", 
    "@ionic-native/spinner-dialog": "^4.4.2", 
    "@ionic-native/splash-screen": "4.4.0", 
    "@ionic-native/sqlite": "^4.4.2", 
    "@ionic-native/sqlite-porter": "^4.5.0", 
    "@ionic-native/status-bar": "4.4.0", 
    "@ionic/storage": "^2.1.3", 
    "angular2-natural-sort": "0.0.2", 
    "angular2-swagger-client-generator": "0.0.22", 
    "cordova-android": "6.3.0", 
    "cordova-plugin-advanced-http": "^1.9.0", 
    "cordova-plugin-browsertab": "^0.2.0", 
    "cordova-plugin-compat": "^1.2.0", 
    "cordova-plugin-device": "^1.1.4", 
    "cordova-plugin-file": "^5.0.0", 
    "cordova-plugin-ionic-webview": "^1.1.16", 
    "cordova-plugin-native-spinner": "^1.1.3", 
    "cordova-plugin-secure-storage": "^2.6.8", 
    "cordova-plugin-splashscreen": "^4.0.3", 
    "cordova-plugin-statusbar": "^2.3.0", 
    "cordova-plugin-whitelist": "^1.3.1", 
    "cordova-sqlite-storage": "^2.1.2", 
    "ionic-angular": "3.9.2", 
    "ionic-plugin-deeplinks": "^1.0.15", 
    "ionic-plugin-keyboard": "^2.2.1", 
    "ionicons": "3.0.0", 
    "ngx-order-pipe": "^1.1.1", 
    "rxjs": "5.5.2", 
    "sw-toolbox": "3.6.0", 
    "swagger-angular-generator": "^1.2.1", 
    "uk.co.workingedge.cordova.plugin.sqliteporter": "^1.0.2", 
    "zone.js": "0.8.18" 
    }, 
    "devDependencies": { 
    "@ionic/app-scripts": "3.1.4", 
    "typescript": "2.4.2" 
    }, 
    "description": "An Ionic project", 
    "cordova": { 
    "plugins": { 
     "ionic-plugin-keyboard": {}, 
     "cordova-plugin-whitelist": {}, 
     "cordova-plugin-device": {}, 
     "cordova-plugin-splashscreen": {}, 
     "cordova-plugin-ionic-webview": {}, 
     "cordova-plugin-browsertab": {}, 
     "ionic-plugin-deeplinks": { 
     "URL_SCHEME": "_CUSTOMURLSCHEME", 
     "DEEPLINK_SCHEME": "https", 
     "DEEPLINK_HOST": "localhost", 
     "ANDROID_PATH_PREFIX": "/", 
     "ANDROID_2_PATH_PREFIX": "/", 
     "ANDROID_3_PATH_PREFIX": "/", 
     "ANDROID_4_PATH_PREFIX": "/", 
     "ANDROID_5_PATH_PREFIX": "/", 
     "DEEPLINK_2_SCHEME": " ", 
     "DEEPLINK_2_HOST": " ", 
     "DEEPLINK_3_SCHEME": " ", 
     "DEEPLINK_3_HOST": " ", 
     "DEEPLINK_4_SCHEME": " ", 
     "DEEPLINK_4_HOST": " ", 
     "DEEPLINK_5_SCHEME": " ", 
     "DEEPLINK_5_HOST": " " 
     }, 
     "cordova-plugin-secure-storage": {}, 
     "cordova-plugin-native-spinner": {}, 
     "cordova-plugin-advanced-http": {}, 
     "cordova-sqlite-storage": {}, 
     "cordova-plugin-statusbar": {}, 
     "uk.co.workingedge.cordova.plugin.sqliteporter": {} 
    }, 
    "platforms": [ 
     "android" 
    ] 
    } 
} 
+0

いくつかのヒント:エンドポイントから取得できる応答に一致するインターフェイス定義を追加します。以前のインターフェイスに基づいて、取得したい最終結果を定義するインターフェイスを追加します。明示的なパラメータと戻り値の型をプロバイダ/サービスメソッドに追加します。私はまだpplが最も重要な機能なしでtypescriptを使用する理由を理解していません... –

答えて

0

あなたが使用をしなければなりませんObservablesは冷たいので、それらを作成し、配列に格納してから、あなたのHTTPリクエストが同時に起動され、必要なすべての情報が収集されます。ここで

は擬似コード(私はあなたが持っている全体の実装をコピーしないように)、あなたの問題を解決する観察可能なチェーンでは、次のとおりです。

getSkillGroups() { 
    this.http.get(this.apiRoot + 'universe/categories/16/', {}, {Authorization: 'Basic YWUxYmIzZDU4ZmRiNDk1ZDk3ZTE1ZTE0OTIyZDc0ZDk6MnpsVjNLZzVHbTh4OHY5b2lUSENYOHVXR21PYjlHd2Rqc3htQ0NHOA=='}) 
     .switchMap(response1 => { 
      const groupsDetails: Observable<any>[] = []; 
      response1.groups.forEach(group => { 
       groupsDetails.push(this.getSkillsInGroup(group)); 
      }); 
      //This will return an array of requests ready to be fired right when you call subscribe on it 
      // When fired, the requests will be parallels, not sync. 
      return Observable.combineLatest(groupsDetails); 
     }); 
} 

getSkillsInGroup(id){ 
    return this.http.get(this.apiRoot + 'universe/groups/' + id + '/', { }, { Authorization: 'Basic YWUxYmIzZDU4ZmRiNDk1ZDk3ZTE1ZTE0OTIyZDc0ZDk6MnpsVjNLZzVHbTh4OHY5b2lUSENYOHVXR21PYjlHd2Rqc3htQ0NHOA=='}) 
     .map(response2 => response2.data); 
} 

あなたがgetSkillGroups()を呼び出したら、response2の配列を取得しますこれは、新規のmap演算子をこれに追加し、Observableの配列を作成してスキルに詳細を追加することを意味します。その後、あなたはそれに加入することができますし、スキルを取得します。

Observableは、Observableがdo演算子を使用してデータを変更せずにさらに多くのことを行い、簡単にデバッグできるように、このような大きなケースでは約束の代わりに使用することを強くお勧めします。

詳細はrxjs officiel documentation websiteです。

+0

私はいつも完全に.mapの部分によって失われてきましたか?あなたはそれが何をしているのか、なぜそれがなぜ違うのかを説明できますか? –

+0

主な部分は、 'map'はobservableを引き起こさず、.thenは(実際には約束を作成することで約束を引き起こす)ことです。基本的に地図演算子は入力値を別の値に変換します(私は間違いを犯したことに気付きました、switchMapでなければなりません)。したがって、mapは "前の演算子からの戻り値を使用して、この値を返します"。 switchMapは "返された値を使用して、このObservableの結果を返します"と似ています。このスキーマを確認してください:http://reactivex.io/documentation/operators/map.htmlマップを理解するのが大いに役立ちます。 – Supamiu

+0

今私は完全に失われている:Dだから、あなたはどのようにこれを動作させるためにサブスクライブを使用するのですか? –

関連する問題