You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现Selector结果映射及多WebSocket数据源数据聚合?

问题解答

1. 当前selectLiveBalances写法的可行性

功能上这个写法能生成你需要的数组,但存在性能隐患:

  • 每次调用balances.map(...)都会返回全新的数组引用,哪怕内部每个selectLiveBalanceByCode的结果都没变化,这个selector也会触发下游(比如求和selector)重新计算。
  • 如果selectLiveBalances是基于createCachedSelector定义的,但当前写法没正确配置缓存依赖/key,缓存机制大概率没生效,等于浪费了createCachedSelector的优化能力。

2. 优化后的聚合Selector方案

第一步:确保单个余额Selector的缓存有效性

先保证selectLiveBalanceByCode是正确memoized的,能稳定合并两个adapter的数据:

import { createSelector } from '@reduxjs/toolkit'

// 合并两个adapter的单币种余额数据
export const selectLiveBalanceByCode = createSelector(
  [
    (state, code) => state.balanceAdapter1.entities[code],
    (state, code) => state.balanceAdapter2.entities[code]
  ],
  (balanceFromAdapter1, balanceFromAdapter2) => {
    // 根据需求合并计算,这里以金额求和为例
    return {
      code,
      total: (balanceFromAdapter1?.amount || 0) + (balanceFromAdapter2?.amount || 0),
      // 可添加其他需要的字段,比如两个adapter各自的明细
      adapter1Amount: balanceFromAdapter1?.amount || 0,
      adapter2Amount: balanceFromAdapter2?.amount || 0
    } as LiveBalanceValue
  }
)

第二步:修正selectLiveBalances的缓存逻辑

用createCachedSelector结合自定义缓存key,确保只有当币种列表或对应余额变化时才重新生成数组:

import { createCachedSelector } from 'reselect'

export const selectLiveBalances = createCachedSelector(
  [selectBalanceCurrencies, (state) => state],
  (currencyCodes, state) => {
    return currencyCodes.map(code => selectLiveBalanceByCode(state, code))
  },
  {
    // 用币种列表的拼接字符串作为缓存key,比JSON.stringify更高效
    keySelector: (state) => selectBalanceCurrencies(state).join(',')
  }
)

第三步:实现总计与部分总计Selector

基于优化后的selectLiveBalances,直接做聚合计算即可,reselect会自动缓存求和结果:

// 所有余额的总计
export const selectTotalLiveBalance = createSelector(
  [selectLiveBalances],
  (balances) => {
    return balances.reduce((sum, item) => sum + item.total, 0)
  }
)

// 自定义筛选的部分总计(支持传入指定币种列表)
export const selectPartialLiveBalance = createSelector(
  [selectLiveBalances, (_, targetCodes) => targetCodes],
  (balances, targetCodes) => {
    return balances
      .filter(item => targetCodes.includes(item.code))
      .reduce((sum, item) => sum + item.total, 0)
  }
)

关键注意点

  • 缓存key优化:如果币种代码是字符串/数字,用join(',')比JSON.stringify性能更好;如果是复杂类型,再考虑用字符串序列化。
  • 保持纯函数:所有Selector里不能有异步操作、修改外部状态等副作用,确保输入相同则输出一定相同。
  • 依赖精准性:每个Selector的依赖要精准,避免不必要的重新计算。

内容的提问来源于stack exchange,提问作者Myles Wardell

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 04:02:46