Redux Saga派发action前存入localStorage有延迟该如何解决?
localStorage.setItem 本身是同步API,正常执行完成后下一行代码就能读取到存储的值,你遇到的所谓“延迟”大概率是两个常见原因:
- 代码存在命名冲突:你当前的generator函数名和
call调用的登录接口方法同名,会触发无限递归,导致接口返回、存储的逻辑都无法正常按顺序执行 - 后续读取token的逻辑不在当前saga执行顺序内,没有等存储完成就触发了
修复方案
首先先修正命名冲突的问题,再把存储操作通过saga的call effect调用,保证这步操作完成后才执行后续的派发action、路由跳转逻辑,同时支持后续扩展成异步存储方案无需修改saga核心逻辑:
- 先封装独立的存储工具函数,也可以根据需要改成Promise版本兼容异步存储场景
// 同步版本,适配localStorage const setTokenToLocal = (token) => localStorage.setItem('token', token) // 可选Promise版本,后续如果要换成AsyncStorage、IndexedDB等异步存储可以直接替换,saga代码不用改 // const setTokenToLocal = (token) => { // return new Promise((resolve) => { // localStorage.setItem('token', token) // resolve() // }) // }
- 修正后的saga代码:
// generator函数改名,避免和登录接口方法重名 function* loginHandler(obj) { // call调用的是你封装的登录接口请求方法,比如api.login,不要和当前generator函数重名 const res = yield call(api.login, obj) if (res.data.token) { // 用call调用存储方法,saga会保证这步完全执行完成后才走后续逻辑 yield call(setTokenToLocal, res.data.token) yield put(Success(res)) if (res.data.isAdmin) { history.push('/admin') } else if (res.data.userType === 'student') { history.push('/student') } // 可选优化:路由跳转也可以走redux action流,方便追踪和拦截,需要配合connected-react-router使用 // if (res.data.isAdmin) { // yield put(push('/admin')) // } else if (res.data.userType === 'student') { // yield put(push('/student')) // } } else { yield put(Error(res.message)) } }
关于Promise的疑问
当前场景用localStorage本身不需要额外封装Promise,但是封装成Promise返回的形式没有额外成本,还能兼容后续异步存储的扩展需求,是可以使用的。
内容的提问来源于stack exchange,提问作者Wani
相关产品推荐
相关产品推荐

