RxJS concatMap串联串行操作时如何访问初始迭代concurso对象
问题原因
RxJS 中链式调用的concatMap默认仅接收紧邻上游操作符返回的结果,平铺链式写法下,初始传入的concurso对象在第一个接口调用完成后没有被继续向下游传递,导致第三个接口调用的作用域无法访问到当前迭代的原始实体。
解决方案
方案1:嵌套concatMap利用闭包保留上下文(推荐)
将同一个concurso对应的三次接口调用放在同一个concatMap的闭包作用域内,后续步骤可以直接访问当前迭代的原始concurso对象,逻辑和执行顺序完全匹配需求,代码如下:
estudiarConcursos() { of(...this.data.data.filter(d => d.estudiar == 'Sí')) .pipe( concatMap(concurso => { // 1. 更新当前concurso的Estudiar字段 return this.dataServiceConcursos.ConcursoEstudiar(concurso).pipe( concatMap(updatedConcurso => { // 如需存储处理后的concurso,放在当前作用域即可,避免全局变量被遍历覆盖 this.concursoTratado = updatedConcurso; // 2. 创建关联oferta对象 return this.dataServiceOfertas.postOferta(this.ConvertirConcursoEnOferta(updatedConcurso)); }), concatMap(createdOferta => { // 3. 关联concurso和新创建的oferta,此处可直接访问闭包内的原始concurso return this.dataServiceConcursos.asociarOferta({ concurso: concurso, oferta: createdOferta }); }) ) }) ) .subscribe(console.log); }
方案2:多值打包透传
如果偏好平铺的链式结构,可以在每一步接口返回后,将后续步骤需要用到的上下文值和当前接口返回值打包为对象,逐层向下游传递:
estudiarConcursos() { of(...this.data.data.filter(d => d.estudiar == 'Sí')) .pipe( concatMap(concurso => this.dataServiceConcursos.ConcursoEstudiar(concurso) .pipe(map(updatedConcurso => ({ concurso, updatedConcurso }))) ), concatMap(({ concurso, updatedConcurso }) => this.dataServiceOfertas.postOferta(this.ConvertirConcursoEnOferta(updatedConcurso)) .pipe(map(createdOferta => ({ concurso, createdOferta }))) ), concatMap(({ concurso, createdOferta }) => this.dataServiceConcursos.asociarOferta({ concurso: concurso, oferta: createdOferta }) ) ) .subscribe(console.log); }
注意:原代码中使用类全局属性
this.concursoTratado存储中间值的写法存在值覆盖风险,遍历多个concurso时会出现中间值错乱的问题,建议将中间值存在当前迭代的闭包作用域内。
内容的提问来源于stack exchange,提问作者kintela
相关产品推荐
相关产品推荐

