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

如何在不同文件的redux-observable epic之间共享变量?

有三种常见的实现方案,可按你的业务场景选择:


方案1:抽离共享变量到公共模块(适合纯客户端场景)

把共享变量单独放到一个公共模块文件,两个epic分别引入该模块读写即可:

  1. 新建shared/index.js存储共享变量
// shared/index.js
export let sharedVariable = null
// 封装赋值方法避免直接篡改
export const setSharedVariable = (val) => {
  if (!sharedVariable) sharedVariable = val
}
  1. epics1.js 中引入赋值
import { setSharedVariable } from './shared'
import { A } from 'xxx'
// 其他引入省略

const epic1 = (action$, state$) => {
  return action$.pipe(
    filter(action1.match),
    tap(() => setSharedVariable(new A())),
    mergeMap((action) => {
      // 原有逻辑
    })
  )
}
export default epic1
  1. epics2.js 中引入读取
import { sharedVariable } from './shared'
// 其他引入省略

const epic2 = (action$, state$) => {
  return action$.pipe(
    filter(action2.match),
    map(() => sharedVariable ? action3() : action4())
  )
}
export default epic2

注意:该方案在Next.js SSR/SSG场景下会出现状态污染,Node.js服务端的模块是单例缓存的,多个用户请求会共享同一个变量,因此仅适合纯客户端运行的场景。


方案2:存储到Redux Store(最推荐,适配全场景)

符合Redux单向数据流设计,状态可追溯,天然支持SSR下每个请求独立store的特性,不会出现状态污染:

  1. 新增shared状态切片
// store/slices/sharedSlice.js
import { createSlice } from '@reduxjs/toolkit'
const initialState = { aInstance: null }
const sharedSlice = createSlice({
  name: 'shared',
  initialState,
  reducers: {
    setAInstance: (state, action) => {
      if (!state.aInstance) state.aInstance = action.payload
    }
  }
})
export const { setAInstance } = sharedSlice.actions
export const selectAInstance = state => state.shared.aInstance
export default sharedSlice.reducer
  1. 修改epics1.js赋值逻辑
import { setAInstance } from 'store/slices/sharedSlice'
import { A } from 'xxx'

const epic1 = (action$, state$) => {
  return action$.pipe(
    filter(action1.match),
    mergeMap(() => {
      const instance = new A()
      // 先派发action把实例存入store
      return of(setAInstance(instance)).pipe(
        // 后续原有逻辑
      )
    })
  )
}
  1. 修改epics2.js读取逻辑
import { selectAInstance } from 'store/slices/sharedSlice'

const epic2 = (action$, state$) => {
  return action$.pipe(
    filter(action2.match),
    map(() => {
      const instance = selectAInstance(state$.value)
      return instance ? action3() : action4()
    })
  )
}

方案3:使用redux-observable依赖注入(适合需要解耦测试的场景)

利用redux-observable内置的依赖注入能力,把共享变量作为全局依赖传入所有epic,方便单元测试时替换mock依赖:

  1. 创建epic中间件时传入依赖
// store/epic.js
import { createEpicMiddleware, combineEpics } from 'redux-observable'
import epic1 from './epics1'
import epic2 from './epics2'

const rootEpic = combineEpics(epic1, epic2)
export const epicMiddleware = createEpicMiddleware({
  dependencies: {
    // 用对象包裹方便引用修改,直接传基础类型无法修改
    shared: { value: null }
  }
})
epicMiddleware.run(rootEpic)
  1. epics1.js 从第三个参数拿依赖赋值
const epic1 = (action$, state$, deps) => {
  return action$.pipe(
    filter(action1.match),
    tap(() => {
      if (!deps.shared.value) deps.shared.value = new A()
    }),
    mergeMap((action) => {
      // 原有逻辑
    })
  )
}
  1. epics2.js 从第三个参数拿依赖读取
const epic2 = (action$, state$, deps) => {
  return action$.pipe(
    filter(action2.match),
    map(() => deps.shared.value ? action3() : action4())
  )
}

注意:该方案同样存在SSR下状态污染问题,仅适合纯客户端场景使用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 17:45:08