You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
如果一条数据已经上传到了服务器,我们还需要记录下这条数据在服务器数据库中的 id。当然,也可以由客户端生成数据的 id 并保存到服务端,这样客户端和服务器端的 id 就是一致的,但这里我们暂时假设服务端对每条同步的数据都另外生成了 id,为了跟客户端数据的 id 做区分,我们用 _id 表示服务器数据库的 id。
我最近要做一个离线数据同步的的功能,这次把我的实现过程记录下来。
场景
一个待办事项 APP,可以离线使用、支持多个端,要求是多个端的数据都是同步的。
大致思路
按照这个思路,我们就可以把示例代码写出来了:
接下来,我们再来一一实现这段代码中的各个功能函数。
读取 / 设置上次更新时间 getLastSyncTime / setLastSyncTime
这两个方法由客户端提供的能力来实现。比如在网页端,我们可以把这个时间用 localStorage 来保存:
保存 / 删除客户端数据 saveToLocalDB / deleteLocalDB
这两个方法同样由客户端提供的能力来实现。比如在网页端,我们可以用 IndexedDB 来保存数据。下面的示例代码使用了 Dexie.js 来操作 IndexedDB:
ITodoItem
的结构会在后面介绍getLocalDBChanges
的实现时讲到。从服务器获取数据 getDataFromServer
服务器端需要有一个能获取数据的接口,用于在用户登录的时候将服务器的所有数据下载到客户端或者在更新时下载特定 id 的数据,代码示例如下:
收集客户端数据库的变更 getLocalDBChanges
在实现这个方法时,就要涉及到数据的结构了。假设我们用如下的结构表示一条待办数据:
但为了能收集到客户端数据库的变更,我们还需要添加一些字段。
同步状态字段 syncStatus
当用户在客户端新增了一条待办事项时,我们需要一个字段用于表示这条数据还没有同步到服务器端。我们可以加一个
syncStatus
字段,0 表示未同步,1 表示已同步,用 JSON 表现形式如下:服务器数据库 id 字段
如果一条数据已经上传到了服务器,我们还需要记录下这条数据在服务器数据库中的 id。当然,也可以由客户端生成数据的 id 并保存到服务端,这样客户端和服务器端的 id 就是一致的,但这里我们暂时假设服务端对每条同步的数据都另外生成了 id,为了跟客户端数据的 id 做区分,我们用 _id 表示服务器数据库的 id。
所以如果一条代办事项数据已经保存在服务器中了,我们再添加一个
_id
字段保存这条待办事项在服务器数据库中的 id,用 JSON 的表现形式是这样的:标记为已删除的字段
当我们在客户端删除已经保存在服务器数据库中的数据时,我们只能将这条数据标记为已删除,不能真的删除它,这样当我们收集客户端数据库变更的时候就能收集到用户的删除操作。我们再新增一个
deleted
字段用于将一条已经同步到数据库中的数据标记为已删除:小结
最后,
ITodoItem
变成了这样:同时,我们在操作客户端数据库时需要注意以下几点:
deleted
为true
的数据;syncStatus
设置为0
;_id
,则将syncStatus
设置为0
且deleted
设为true
;如果没有_id
,可以直接删除。修改数据的情况暂时不在这篇文章的讨论范围之内,但看完之后,加上修改数据的同步也不是难事。
具体实现
有了前面添加的这些字段,我们就可以很容易收集到客户端数据库的变更了,示例代码如下:
上传客户端数据库变更并获取服务器数据库的变更日志 getRemoteDBChanges
服务器需要提供一个接口,接收客户端提交过来的数据库变更和此客户端上次检查更新的时间,服务器则返回这段时间内服务器数据库发生的所有变更和服务器时间。
示例代码如下:
总结
到了这里,整个实现思路就完成了,但还有一些细节需要完善:
抛砖引玉,欢迎大家给出不同的看法。
The text was updated successfully, but these errors were encountered: