[英]Combine observable responses into one
如何从多个可观察对象中获取对象响应?
我的史诗喜欢这样:
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({}))
});
});
}
我需要的是通过我的功能getMetaDataSuccess()
从响应对象courierApi()
itemCategoriesApi()
和airportsApi()
这样的getMetaDataSuccess({ couriers, items, airports })
但首先我需要等待所有的三个承诺完成并以某种方式在对象中组合作为响应。
我的代码现在所做的是打印来自API的响应,从而调用getMetaDataSuccess
3次。 enter code here
听起来你想要这样的东西。
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
aka mergeMap
可以直接在Promise和Arraylike值上运行。 这里我们使用Promise.all
来等待多个Promises的结果。 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>
我有两个解决方案,你可以尝试一下,如果他们在你的情况下工作:
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));
});
});
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.