我有一个对象,需要填充必须从网上获取的信息。新信息应存储在同一对象内
例如:
const apps = {
com.foobar.bar: {
title:pancake,
existingInfo: bar
},
com.company.android: {
title: foobar,
existingInfo: barfoo
}
}
对于应用程序内的每个ID,我想调用rest API,它将提供一些我可以添加到对象中的附加字段。 该流不应等待所有其余的调用完成,而应从返回初始值开始,然后为它收到的每个restcall发出一个更新的对象。
其余任何一次调用第一次返回时,应仅填充正确的字段。
{
com.foobar.bar: {
title:pancake,
existingInfo: bar,
newStuff: foobar //let say this is the response we get from the first restcall
},
com.company.android: {
title: foobar,
existingInfo: barfoo
}
}
更新: 我设法使代码正常工作,但我认为可以用其他方法来完成。
const apps$ = of(apps).pipe(
mergeMap((apps:any) => { //**1**
const appPromise = Object.keys(apps).map((appId) => {
return fetchExternalAppInfo(appId).pipe(take(1));
})
appP.unshift(of(apps));
return of(appP).pipe(mergeAll())
}),
mergeAll(),
scan((acc, curr) => { //**2**
if (!acc) {
acc = curr;
} else {
acc[curr.appId] = Object.assign(acc[curr.appId], curr)
}
return acc
}, null),
map((result) => { //converting to an array which is ordered by title
return _.orderBy(result, 'title')
}),
)
** 1 =这将返回一个Observable数组,该数组必须直接传递给mergeAll()。这是订阅并合并Observable数组的正确方法吗?
** 2 =我知道传递给该函数的第一个对象是我的初始值(appPromise.unshift(of(apps)))。这就是我可以保留旧的初始值并为其添加新值的方法。
*更新2 *
这是另一种解决方案,我认为这要好得多:在这里,我使用CombineLates编辑初始对象。
const fetchedApps$ = applist$.pipe(
mergeMap((apps:any) => { //*1
const appPromise = Object.keys(apps).map((appId) => {
return fetchExternalAppInfo(appId).pipe(take(1));
})
return of(appP).pipe(mergeAll())
}),
mergeAll(),
scan((acc, curr:any = {}) => {
acc[curr.appId] = curr;
return acc;
}, {}),
);
const apps$ = combineLatest(of(apps), fetchedApps$).pipe(
map(([a,b]) => {
return _.merge(a,b)
}),
map((result) => {
return _.orderBy(result, 'title')
}),
// * 1 除了两次调用 mergeAll()之外,还有其他方法可以在一系列可观察对象上“开始订阅”吗?
答案 0 :(得分:1)
我认为您已经非常接近最佳解决方案。通过您的代码阅读,我认为这些提示可以帮助你提高代码:
from
变换值的阵列成值的流,这样,那些Object.keys
可以被合并到外可观察
scan
可设有apps
作为初始值,即应删除需要后来合并(只要我不会遗漏任何东西)
startWith
可让我们在一个初始值潜行,这样可以实现即时第一通知
这可能是一个实现:
const fetchedApps$ = applist$.pipe(
mergeMap((apps:any) => from(Object.keys(apps))),
mergeMap(key => fetchExternalAppInfo(key).pipe(first())),
scan((acc, curr:any = {}) => {
acc[curr.appId] = curr;
return acc;
}, apps),
startWith(apps),
map(result => _.orderBy(result, 'title'))
);
告诉我这是否适合您或者您的代码中有哪些阻止