Angular 5中RxJS管道操作符顺序疑问:为何前后tap输出值一致?
问题根源:引用类型的“共享”特性
嘿,你完全没搞错RxJS管道的执行顺序!问题出在JavaScript的引用类型处理上,不是RxJS的锅~
咱们来拆解你的代码逻辑:
- 第一个
tap拿到的x是上游map传递过来的数组(也就是result.result.data) - 中间的
map里用forEach遍历数组,直接修改了每个material对象的type属性 - 第二个
tap拿到的x和第一个tap里的x是同一个数组引用
因为数组和对象都是引用类型,你修改数组元素的属性时,并没有创建新的对象或数组,只是修改了原引用指向的内容。加上浏览器控制台会实时更新引用类型的展示,所以哪怕第一个tap先执行打印,当你后续在控制台展开这个数组时,看到的已经是被修改后的状态了,看起来就像两个tap输出了相同的值。
解决方案:创建新的对象/数组,避免修改原引用
把中间的forEach改成map,返回全新的对象,这样就不会影响原始数据了:
return this.pcs.getAvailableMaterials(currentProduct.id).pipe( map( result => result.result.data ), tap( x => console.log(x, 'before') ), map( materials => materials.map(material => ({ ...material, type: 'material' // 新增属性,不修改原对象 })) ), tap( x => console.log(x, 'after') ), tap( materials => { setState({ ...state, availableMaterials: materials }) }) );
这样一来,第一个tap打印的是原始数组(没有type属性),第二个tap打印的是包含新对象的数组(每个对象都有type: 'material'),就能看到你预期的差异了。
内容的提问来源于stack exchange,提问作者Dirk
相关产品推荐
相关产品推荐

