将可观察到的响应合并为一个
Combine observable responses into one
如何从多个可观察对象获得 object 响应?
我的史诗是这样的:
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()
[=15] =] 但首先我需要等待所有 3 个承诺完成并以某种方式组合成 object 作为响应。
我的代码现在所做的是打印来自 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
来等待多个 Promise 的结果。 Promise.all
returns 解析为数组的 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));
});
});
}
如何从多个可观察对象获得 object 响应?
我的史诗是这样的:
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()
[=15] =] 但首先我需要等待所有 3 个承诺完成并以某种方式组合成 object 作为响应。
我的代码现在所做的是打印来自 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
来等待多个 Promise 的结果。 Promise.all
returns 解析为数组的 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));
});
});
}