Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/364.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 将高阶可观测对象合并到现有对象中_Javascript_Rxjs - Fatal编程技术网

Javascript 将高阶可观测对象合并到现有对象中

Javascript 将高阶可观测对象合并到现有对象中,javascript,rxjs,Javascript,Rxjs,我有一个对象需要填充信息,我必须通过网络获取这些信息。新信息应存储在同一对象中 例如: 对于应用程序中的每个id,我想调用一个RESTAPI,它将为我的应用程序提供一些可以添加到对象中的附加字段。 流不应该等待所有rest调用完成,它应该从返回初始值开始,然后为接收到的每个rest调用发出一个更新的对象 第一次任何rest调用返回时,它应该只填充正确的字段 { com.foobar.bar: { title:pancake, existingInfo:

我有一个对象需要填充信息,我必须通过网络获取这些信息。新信息应存储在同一对象中

例如:

对于应用程序中的每个id,我想调用一个RESTAPI,它将为我的应用程序提供一些可以添加到对象中的附加字段。 流不应该等待所有rest调用完成,它应该从返回初始值开始,然后为接收到的每个rest调用发出一个更新的对象

第一次任何rest调用返回时,它应该只填充正确的字段

{
    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=这将返回必须直接传递给mergeAll()的可观察数组。这是订阅和合并一组可观测数据的正确方法吗

**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()之外,还有其他方法可以“开始订阅”一组可观察对象吗?

我认为您已经非常接近最佳解决方案了。通读您的代码,我认为这些提示可以帮助您改进代码:

  • from
    将一个值数组转换为一个值流,这样那些
    对象键就可以合并到外部可观察对象中

  • 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'))
);

告诉我这是否适用于您,或者您的代码中是否存在阻止

到目前为止您尝试了什么?请发布您尝试的代码。StackOverflow希望您能这样做,因为您的尝试有助于我们更好地了解您的需求。请编辑问题以说明您在a中遇到的具体问题。@dmcgrandle我现在已更新了我的问题。它可以工作,但应用程序实际上是可观察的,因此我不能使用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'))
);