2017-12-22 9 views
1

複数の観測値からオブジェクト応答を取得するにはどうすればよいですか?私のエピックがある観測可能な応答を1つに結合する

はこの好き:私は必要なのは、このgetMetaDataSuccess({ couriers, items, airports })ようcourierApi()itemCategoriesApi()airportsApi()からの応答で私の機能getMetaDataSuccess()にオブジェクトを渡すことですが、最初に私はすべての3つの約束を待つ必要が

export function metaDataEpic(action$: ActionsObservable<metaDataActions>) { 
    return action$.ofType(META_DATA_REQUEST) 
     .mergeMap((action: metaDataActions) => { 
     const { language } = action; 
     return Observable.merge(
      Observable.fromPromise(couriersApi().then(r => r.json())), 
      Observable.fromPromise(itemCategoriesApi({ language }).then(r => r.json())), 
      Observable.fromPromise(airportsApi().then(r => r.json()))) 
      .flatMap(res => { 
      console.log(res); 
      return Observable.of(getMetaDataSuccess({})) 
      }); 
     }); 
} 

終了し、何らかの形で応答としてオブジェクトに結合します。

私のコードでは、APIの応答を印刷して、getMetaDataSuccessを3回呼び出しています。 enter code here

答えて

2

あなたはこのようなものが欲しいのですか? mergeMap別名

export function metaDataEpic(action$: ActionsObservable<metaDataActions>) { 
    return action$.ofType(META_DATA_REQUEST) 
     .flatMap(({language}) => Promise.all([ 
      couriersApi(), 
      itemCategoriesApi({language}), 
      airportsApi() 
      ].map(p => p.then(r => r.json())) 
     ) 
     .then(([couriers, items, airports]) => ({couriers, items, airports})) 
    ) 
     .do(console.log) 
     .map(getMetaDataSuccess); 
} 

flatMap約束とArraylike値を直接操作することができます。ここでは、複数の約束の結果を待つためにPromise.allを使用しています。 Promise.allは、各要素が入力配列内の対応する項目の結果である配列に解決されるPromiseを返します。この配列をオブジェクトに変換して渡します。

ダミーデータが動作していることを示しています。

function couriersApi() { 
 
    return Promise.resolve({ 
 
    json:() => [{ 
 
     name: 'x', 
 
     id: 1 
 
    }, { 
 
     name: 'y', 
 
     id: 2 
 
    }] 
 
    }); 
 
} 
 

 
function airportsApi() { 
 
    return Promise.resolve({ 
 
    json:() => [{ 
 
     name: 'ORF', 
 
     id: 1 
 
    }, { 
 
     name: 'JFK', 
 
     id: 2 
 
    }] 
 
    }); 
 
} 
 

 
function itemCategoriesApi({language}) { 
 
    return Promise.resolve({ 
 
    json:() => [{ 
 
     name: 'a', 
 
     language: 'German' 
 
     }, 
 
     { 
 
     name: 'b', 
 
     language: 'English' 
 
     }, 
 
    ].filter(c => c.language === language) 
 
    }); 
 
} 
 
const META_DATA_REQUEST = undefined; 
 
const action$ = { 
 
    ofType:() => Rx.Observable.of({ 
 
    language: 'English' 
 
    }) 
 
}; 
 

 
metaDataEpic(action$) 
 
    .subscribe(); 
 

 
function getMetaDataSuccess(o) { 
 
    console.log(o.couriers); 
 
    console.log(o.items); 
 
    console.log(o.airports); 
 
} 
 

 
function metaDataEpic(action$) { 
 
    return action$.ofType(META_DATA_REQUEST) 
 
    .flatMap(({ 
 
     language 
 
     }) => Promise.all([ 
 
     couriersApi(), 
 
     itemCategoriesApi({ 
 
      language 
 
     }), 
 
     airportsApi() 
 
     ].map(p => p.then(r => r.json()))) 
 
     .then(([couriers, items, airports]) => ({ 
 
     couriers, 
 
     items, 
 
     airports 
 
     })) 
 
    ) 
 
    .do(console.log) 
 
    .map(getMetaDataSuccess); 
 
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.5.6/Rx.js"></script>

+0

あなたは括弧が欠落しています'r.json())' 'Promise.all(' また、私は試みましたが、console.log – user3610155

+0

@ user3610155感謝していません、私はタイプミスを修正し、ライブデモを追加しました。それを実行し、それは動作します。 –

1

私は、彼らはあなたのケースで作業する場合、あなたが試すことができ、私の心に2つのソリューションを持っている:

export function metaDataEpic(action$: ActionsObservable<metaDataActions>) { 
    return action$ 
    .ofType(META_DATA_REQUEST) 
    .mergeMap((action: metaDataActions) => { 
     const {language} = action; 

     const requestObservable = Observable.zip(
      Observable.fromPromise(couriersApi().then(r => r.json())), 
      Observable.fromPromise(
       itemCategoriesApi({language}).then(r => r.json()) 
      ), 
      Observable.fromPromise(airportsApi().then(r => r.json())), 
      (couriers, items, airports) => { 
       return Observable.of(getMetaDataSuccess({ couriers, items, airports }))).map(response => response.value) 
      } 
     ).catch(e => { 
      return Observable.of(getMetaDataFail(e)); 
     }); 

     return requestObservable; 
    }); 
} 

または

export function metaDataEpic(action$: ActionsObservable<metaDataActions>) { 
    return action$ 
    .ofType(META_DATA_REQUEST) 
    .mergeMap((action: metaDataActions) => { 
     const {language} = action; 

     Promise.all(
      [couriersApi(), itemCategoriesApi({language}), airportsApi()].map(p => 
       p.then(r => r.json()) 
      ) 
     ) 
     .then(([couriers, items, airports]) => { 
      return Observable.of(getMetaDataSuccess({couriers, items, airports})); 
     }) 
     .catch(e => { 
      return Observable.of(getMetaDataFail(e)); 
     }); 
    }); 
} 
+0

rxjsのために私はこれを使い終わった。私は '.map(response => response.value')をzipに追加してアクションを得なければならなかったのですが、 – user3610155

+0

私は' return getMetaDataSuccess({couriers、items、airports});を試すことができますか? 'return Observable.of (getMetaDataSuccess({couriers、items、airports})); – zarcode

+0

私はそれを動作させるために両方を使用しなければならなかった このように: 'return Observable.zip( Observable.fromPromise(couriersApi()。then(r => r == r.json()))、 (couriers、itemCategories)=> Observable.of(getMetaDataSuccess({couriers、itemCategories) })) ).map(response => response.value) ' – user3610155

関連する問題