javascript - 将高阶 Observable 合并到现有对象中

标签 javascript rxjs

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

例如:

const apps = {
com.foobar.bar: {
    title:pancake,  
    existingInfo: bar
    },
com.company.android: {
    title: foobar,
    existingInfo: barfoo
    }
}

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

第一次任何 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() 的 Observable 数组。这是订阅和合并 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() 之外,还有其他方法可以“开始订阅”一组可观察对象吗?

最佳答案

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

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

告诉我这是否适合你,或者你的代码中是否有什么东西阻止了

关于javascript - 将高阶 Observable 合并到现有对象中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54480994/

相关文章:

angular - 仅当第一次失败时才执行第二次 http 调用

angular - 如何使用 RXJS 运算符根据重复值对 Firebase 可观察列表进行排序

redux - 测试 redux-observable 史诗的错误处理

javascript - 如何在免费 jqgrid 中将焦点设置为内联编辑中的自动完成内容

javascript - TinyMCE 编辑器在获取appendTo 后无法工作

javascript - 如何使用 JavaScript 禁用 TextBox?

javascript - Rxjs v6.x 上的类型 'clientX' .ts(2339) 上不存在属性 'Event'

javascript - 如何使用 Angular 6 触发 fadeInRight 效果

javascript - WordPress:使用 get_header() 时,提交按钮上没有任何操作

javascript - switchMap 不接受在其中执行的函数