自动数据备份需分“本地落盘”和“云端同步”两阶段:本地用uni.setstoragesync存小结构化数据(≤1mb),大文件走filesystemmanager存沙箱并记录路径;云端同步须带version乐观锁校验、失败入pending队列、选onlaunch/onnetworkstatuschange/onhide时机重试,防多端覆盖与真机后台限制。

自动数据备份不是开个定时器往云数据库里写就行,得区分“本地落盘”和“云端同步”两个阶段,且每个阶段都有必须绕开的坑。
uni.setStorageSync 为什么存了却读不到
真机杀后台后数据消失、模拟器看着在重启后就没了——根本原因是用了 uni.setStorage(异步+缓存)而不是 uni.setStorageSync(同步+持久化)。iOS suspend、Android 后台回收时,uni.setStorage 的内容大概率被清空。
- 只对小结构化数据用
uni.setStorageSync:用户设置、表单草稿、最后操作时间戳,体积控制在 1MB 以内 - 别把图片、录音、离线包塞进 storage;它们必须走
uni.getFileSystemManager()存到uni.env.USER_DATA_PATH下,并把路径字符串存进 storage - 恢复时不能直接
uni.getStorageSync后就 JSON.parse,得先用uni.getFileSystemManager().access校验文件是否真实存在——路径还在,文件可能已被系统清理
uniCloud.callFunction 同步失败后数据丢了怎么办
网络抖动、用户切后台、App 被杀进程,都可能导致 uniCloud.callFunction 调用失败,如果没兜底机制,这次修改就彻底丢失了。
- 每次上传前,本地数据必须带
version字段(递增数字或时间戳),服务端用db.collection('xxx').where({ _id, version: $lt: clientVersion }).update(...)做乐观锁校验 - 上传失败时,把待同步数据(含 version、_id、变更字段)push 到一个 pending 队列,存为
uni.setStorageSync('sync_pending_queue', [...]) - 重试时机选
onLaunch(冷启动)、onNetworkStatusChange(联网恢复)、onHide(退后台前)——别依赖setInterval,真机后台会被系统限制
云端备份怎么避免多端覆盖同一份数据
用户在手机 A 编辑待办未同步,又在平板 B 改了同一项,B 先上传成功,A 后传直接覆盖——这不是“同步”,是“静默删改”。uniCloud 没内置冲突检测,得自己加。
- 服务端更新逻辑不能用
doc.set或collection.add,必须用doc.update并带上版本条件 - 客户端收到服务端返回的 “version 不匹配” 错误时,要立刻拉取最新版(
db.collection('xxx').doc(_id).get()),再做本地合并或提示用户手动选择 - 别用时间戳当唯一判据——设备时钟不准、NTP 同步延迟会导致误判;优先用服务端生成的
_id+ 客户端自增version组合
什么时候该触发一次完整同步
一有改动就调 uniCloud.callFunction?耗电、费流量、还容易失败。得结合状态机判断是否真正“可同步”。
- 三个条件必须同时满足:网络状态为 online(
uni.getNetworkType返回 wifi 或 4g/5g)、App 处于前台或刚从后台切回、本地 pending 队列非空 - 避免在
onShow里无差别同步——用户只是切了个微信回来,不等于要立刻上传;加个 2 秒防抖,等 UI 渲染完成再检查队列 - Android 真机要注意厂商限制:华为/小米后台保活极严,
onHide后 30 秒内可能就被杀进程,所以onHide触发的同步必须是轻量级的(只推 version 和关键字段,大文件延后)
最易被忽略的点:uni.setStorageSync 写入的是本地,uniCloud.callFunction 推的是云端,二者生命周期完全独立。备份方案失效,往往不是代码写错了,而是没意识到“本地存了≠云端有了”,中间差了一次可靠上传和失败兜底。











