ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Redux Offline Commit 机制详解:在 effect 成功后派发确认动作并安全更新本地状态

Redux Offline Commit 机制详解:在 effect 成功后派发确认动作并安全更新本地状态 前端【免费下载链接】redux-offlineBuild Offline-First Apps for Web and React Native项目地址https://gitcode.com/gh_mirrors/re/redux-offline点击查看免费下载Redux Offline 默认鼓励乐观更新——先立即更新 UI再在后台同步网络请求。但在下单、支付、创建订单等场景中本地状态必须依赖服务器返回的真实结果盲目乐观更新会带来脏数据。meta.offline.commit正是为此设计的确认机制它允许你将状态更新推迟到网络 effect 成功执行之后并把服务器响应作为 payload 派发给 reducer实现真正可靠的离线写入。读完本文你将掌握 commit / rollback 动作的完整定义方式、它们与config.effect、config.defaultCommit、config.defaultRollback的协作原理以及底层send流程中确认动作的派发时机与元数据标注规则。为什么需要 Commit悲观更新场景正如原文档标题所言——悲观主义者永远不会失望A pessimist is never disappointed。Redux Offline 中存在两类写入场景乐观更新Optimistic Updateaction 一经 dispatch 立即更新本地状态网络请求在后台悄悄进行。适用于 UI 结果不依赖服务器响应、且失败代价低的场景。悲观更新Pessimistic Update在 effect 成功执行之前不更新本地状态等待服务器返回真实数据后再落地。适用于订单提交、支付、创建资源等必须拿到服务端确认的场景。当出现以下两种情况之一时你就应该使用 commit 动作必须让用户感知动作真实生效——例如界面需要显示提交成功的最终状态而不是提前假装成功最终 UI 需要来自服务器响应的数据——例如订单完成后服务器返回的订单编号、回执receipt、票据等本地无法生成的信息。此时本地 reducer 需要区分三种动作原始的发起动作COMPLETE_ORDER、成功确认动作COMPLETE_ORDER_COMMIT、失败回滚动作COMPLETE_ORDER_ROLLBACK。定义带 Commit 的离线动作在meta.offline中同时声明effect、commit与rollback即可声明一个悲观更新的离线动作。原文档给出了完整的订单提交示例const completeOrder (orderId, lineItems) ({ type: COMPLETE_ORDER, payload: { orderId, lineItems }, meta: { offline: { effect: //..., // 发送给 effect reconciler 的网络请求描述如 { url, method, body } commit: { type: COMPLETE_ORDER_COMMIT, meta: { orderId }}, rollback: { type: COMPLETE_ORDER_ROLLBACK, meta: { orderId }} } } });对应的 reducer 完整处理三条分支const ordersReducer (state, action) { switch(action.type) { case COMPLETE_ORDER: return { ...state, submitting: { ...state.submitting, [action.payload.orderId]: true } }; case COMPLETE_ORDER_COMMIT: return { ...state, receipts: { ...state.receipts, [action.meta.orderId]: action.payload }, submitting: omit(state.submitting, [action.meta.orderId]) }; case COMPLETE_ORDER_ROLLBACK: return { ...state, error: action.payload, submitting: omit(state.submitting, [action.meta.orderId]) }; default: return state; } }三种动作的分工非常清晰动作触发时机payload典型用途COMPLETE_ORDER用户 dispatch 时用户提交的{ orderId, lineItems }将订单标记为提交中submittingCOMPLETE_ORDER_COMMITeffect 成功返回后服务器响应结果保存回执移除提交中标记COMPLETE_ORDER_ROLLBACKeffect 永久失败后错误对象记录错误移除提交中标记注意 commit / rollback 动作通过meta.orderId关联回原始订单而不是依赖 payload这是 Redux Offline 中常见的关联手法——因为 commit 的 payload 会被服务器响应覆盖见下文源码分析。底层实现Commit 动作是如何被派发的meta.offline.commit的派发逻辑位于 src/send.js 的send函数中。理解这段流程就能明白 commit 动作的 payload 来源与优先级规则成功路径effect resolve 后派发 commitconst send (action, dispatch, config, retries 0) { const metadata action.meta.offline; dispatch(busy(true)); return config .effect(metadata.effect, action) .then(result { const commitAction metadata.commit || ({ ...config.defaultCommit, meta: { ...config.defaultCommit.meta, offlineAction: action } }); try { return dispatch(complete(commitAction, { success: true, payload: result }, action, config)); } catch (error) { return dispatch(handleJsError(error)); } }) // ... };关键结论均有源码依据config.effect(metadata.effect, action)负责真正发起网络请求必须以 Promise 形式返回见 docs/docs/api/config.md 中effect的说明effect 成功 resolve 后其返回值result会作为 commit 动作的 payload 被 dispatch——这正是reducer 中action.payload拿到服务器响应的数据来源优先级规则如果动作自带meta.offline.commit则使用它否则回退到config.defaultCommit并把原始离线动作挂在meta.offlineAction上见 src/defaults/defaultCommit.js。默认 CommitOffline/DEFAULT_COMMIT在 src/defaults/defaultCommit.js 中默认 commit 动作被定义为const defaultCommit { type: DEFAULT_COMMIT // Offline/DEFAULT_COMMIT };常量定义见 src/constants.js。也就是说如果你不在动作里声明commit成功时会收到一个type: Offline/DEFAULT_COMMIT的动作payload 同样是 effect 的返回值。文档 docs/docs/api/config.md 明确指出defaultCommit 仅在离线动作未定义 commit 时使用其 payload 会被设置为 effect reconciler 的结果——与普通 commit 动作行为完全一致。失败路径rollback、discard 与 retry继续看 src/send.js 的失败分支effect 被 reject 后库会先调用config.discard(error, action, retries)判断是否应丢弃该请求若不应丢弃则调用config.retry(action, retries)计算延迟并安排重试只有被判定为永久失败如客户端错误、重试次数耗尽的请求才会派发 rollback.catch(async error { const rollbackAction metadata.rollback || ({ ...config.defaultRollback, meta: { ...config.defaultRollback.meta, offlineAction: action } }); let mustDiscard true; try { mustDiscard await config.discard(error, action, retries); } catch (e) { console.warn(e); } if (!mustDiscard) { const delay config.retry(action, retries); if (delay ! null) { return dispatch(scheduleRetry(delay)); } } return dispatch(complete(rollbackAction, { success: false, payload: error }, action, config)); })这解释了原文档中 rollback 动作的触发条件仅当网络 effect 永久失败时网络类失败会被自动重试不触发 rollback详见 docs/docs/basics/write-resilience.md 对meta.offline.rollback的说明。默认的 rollback 动作类型为Offline/DEFAULT_ROLLBACK见 src/defaults/defaultRollback.js 与 src/constants.js。结果动作的统一标注success 与 completed无论成功还是失败最终派发的动作都会经过complete()函数src/send.js统一包装return ({ ...action, payload: result.payload, meta: { ...action.meta, success: result.success, completed: true } });即每个 commit / rollback 动作都会被打上meta.success布尔值与meta.completed: true标记对应 src/types.js 中ResultAction的类型定义。这为你在中间件或 reducer 中统一识别结果动作提供了稳定信号。若 reducer 在处理 commit/rollback 时抛出异常则会派发Offline/JS_ERROR动作handleJsError见 src/send.js。中间件视角Commit 动作如何触发发送meta.offline.commit不是独立运行的——它依赖 Redux Offline 中间件 src/middleware.js 对离线动作的识别与出队逻辑。流程大致如下每个动作先传给下一个中间件next(action)中间件通过config.queue.peek(offline.outbox, action, context)检查出站队列若存在待发送动作且满足!offline.busy !offline.retryScheduled offline.online则调用send()发送send()内部执行 effect并按上文逻辑派发 commit / rollback。也就是说commit 动作被 dispatch 后最终通过 reducer 更新offline.outboxqueue.dequeue会将已完成或已丢弃的动作移出队列整个提交→执行→确认/回滚链路闭环。测试中的行为契约仓库测试 src/tests/send.js 对上述行为做了明确验证可作为你理解和使用 commit 的参考busy 状态包裹send前后分别派发busy(true)与busy(false)保证发送期间不并发处理其他动作测试用例 dispatches busy actioneffect 被正确调用config.effect会以action.meta.offline.effect和 action 本身作为参数被调用测试用例 requests resource using effects reconciler成功时派发 complete 动作effect resolve 后派发 commit 动作其 meta 中包含completed标记测试用例 dispatches complete action。测试中的配置同时声明了commit: { type: COMMIT }与rollback: { type: ROLLBACK }与文档示例的用法完全一致。实战要点与踩坑提醒结合原文档与源码使用meta.offline.commit时有几个关键点值得留意不要用本地数据覆盖响应数据commit 动作的payload会被 effect 的返回值覆盖complete()中payload: result.payload因此需要关联业务数据时应像示例那样通过meta如meta.orderId携带而非依赖 payload。显式声明 rollback 同样重要如果只声明 commit 而不声明 rollback永久失败时会派发Offline/DEFAULT_ROLLBACK。在订单类场景中建议总是成对声明便于在 reducer 中处理错误状态并清理提交中标记。网络失败不等于 rollback断网、超时等网络类错误会被自动重试默认重试调度见 docs/docs/api/config.md不会立即触发 rollback只有被判为不可重试的错误才会走 rollback 分支。commit 与乐观更新可以混用Redux Offline 允许某些动作乐观更新、某些动作悲观更新只需按需在meta.offline中声明。若完全不需要服务器确认甚至可以不写 commit此时成功后会收到默认 commit 动作。延伸阅读Write Resilience离线动作meta.offlineeffect / commit / rollback在出站队列outbox中的整体设计背景Config 文档defaultCommit、defaultRollback、effect、discard、retry等配置项的完整参数说明Customize Requests自定义 effect reconciler 与丢弃策略的进阶用法Rollback回滚机制的独立专题Getting Started安装与 store 增强器的基本接入方式。赞分享前端【免费下载链接】redux-offlineBuild Offline-First Apps for Web and React Native项目地址https://gitcode.com/gh_mirrors/re/redux-offline点击查看免费下载相关推荐Redux-Saga核心概念详解Effect与Saga工作机制Redux Saga核心概念详解Effect与Saga工作机制 本文深入解析Redux Saga的核心设计理念与执行机制重点探讨Effect系统的声明式编程前端Zustand redux 中间件详解用 Redux 式 action/reducer 驱动状态更新Zustand redux 中间件详解用 Redux 式 action/reducer 驱动状态更新 redux 是 Zustand 提供的一个官方中间件它前端Effect并发安全流流并发控制Effect并发安全流流并发控制 概述 在现代应用开发中处理高并发数据流是常见需求。Effect框架提供了强大的流处理能力通过类型安全的函数式编程范式确后端异步编程依赖注入上一篇CoastSat 潮汐校正完全指南如何消除潮汐影响获取精确海岸线数据下一篇微信数据备份新突破Sharp-dumpkey免费密钥提取工具完整指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表