【问题标题】:Chaining observables sequentially按顺序链接可观察对象
【发布时间】:2018-06-07 21:23:19
【问题描述】:

在 Angular 中,我想在路由 resolve 字段中返回一个对象,其中包含一个列表,并且对于列表中的每个项目,我想执行一个额外的请求来修改它。它看起来像这样:

this.employeesService.getEmployees(route.parent.params['department'])
  .map(employeesResponse => {
    employeesResponse.employees.map(employee => 
      employee.status = this.employeesService.checkStatus(route.parent.params['department'], employee))
  })

getEmployees 返回一个包装响应对象:

{
  operationId: 1
  employees: [],
}

checkStatus 返回一个员工状态字符串。

我知道这行不通,但我尝试了很多不同的方法,但不知道如何实现。我知道从第一个请求返回列表时如何执行此操作,但我必须保留此包装器对象。

使用 Rx 执行此操作的最佳方法是什么?我对反应式编程概念很陌生。

【问题讨论】:

  • 如果我理解正确,您需要 getEmployees 响应对象,但要添加每个员工的状态。您的 employees.map 正在为每个员工添加状态(尽管应该是 forEach)。为什么不在你的 rxjs 映射方法中只使用return employeesResponse

标签: angular typescript rxjs reactive-programming


【解决方案1】:

您可以使用.mergeMap() 和并发参数来同时修改多个项目。这不是保留顺序,因此可能是个问题。

如果需要订购,您可以使用.concatMap()

【讨论】:

    【解决方案2】:

    我可以很容易地实现使用以下代码返回列表(修改后的列表)的结果:

    this.employeesService.getEmployees(route.parent.params['department'])
      .mergeMap((employeesResponse: EmployeesResponse) => employeesResponse.employees)
      .mergeMap((employee: Employee) => this.checkEmployee(route.parent.params['department'], employee)
      .map(statusResponse => {
        employee.status = statusResponse.status;
        return employee
      })
    

    );

    但是,我不想要那个列表。我希望它被包裹在EmployeeResponse 中。这是我有问题的地方,而不是使用哪个运算符。

    【讨论】:

    • mergeMap 将流从数组分解为元素,以便您可以映射每个项目,然后我认为toArray 会将它们重新组合在一起 - 需要模拟一个工作示例才能确定.
    【解决方案3】:

    根据您的回答,但在 mergeMap 中获取状态检查映射并使用 toArray 重建列表。

    唯一丢失的是operationId。这有关系吗?

    // Mock services
    const routeParamsDept = 'Sales';
    const employeesService = {
      getEmployees: (department) => {
        return Rx.Observable.of({
          operationId: 1,
          employees: [
            {name: 'Joe', status: 'Perm', dept: 'Sales'},
            {name: 'Jane', status: 'Temp', dept: 'Sales'}
          ]
        });
      } 
    }
    const checkEmployee = (department, employee) => Rx.Observable.of({status: 'Perm'})
    
    const fetchedAndChecked = employeesService.getEmployees(routeParamsDept)
      .mergeMap(employeesResponse => employeesResponse.employees)
      .mergeMap(employee => {
        return checkEmployee(routeParamsDept, employee)
          .map(statusResponse => {
            employee.status = statusResponse.status;
            return employee
          })
      })
      .toArray()
    
    fetchedAndChecked.subscribe(console.log)
    <script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.5.6/Rx.js"></script>

    【讨论】:

      猜你喜欢
      • 2018-06-03
      • 1970-01-01
      • 2020-01-13
      • 2015-01-12
      • 1970-01-01
      • 1970-01-01
      • 2017-03-31
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多