在SPA(html5单页面应用程序)中是否存在同步本地和远程数据的最佳实践/模式?

时间:2012-12-12 18:43:30

标签: local-storage data-synchronization singlepage single-page-application breeze

我正在用jqueryMobile + knockout + breeze + WebAPI写一个简单的“todo - helloworld” 了解移动环境中的SPA(单页应用程序)(不可靠的互联网连接)

要启用离线使用,WebApp将利用

  • 应用程序缓存
  • localStorage的

应用程序应尽可能使用远程数据库来加载和保存数据,但应该能够在脱机时无缝切换到localstorage并在重新联机时同步本地/远程更改。

现在回到问题: 该应用程序将使用Breeze的EntityManager来管理数据(本地缓存和远程同步)

  • “remoteDb”

为了缓解不一致/并发问题,我会使用2个localstorage密钥:

  • “localDb”表示远程数据库的本地副本(待办事项列表)
  • “localPendingChanges”表示应用无法提交到远程数据库的更改

所以流程或多或少会是(伪代码):

LoadData
  if(online)
    load remoteDb
    save localDb                   // save a local copy of the fresh loaded remotDb
    if(localPendingChanges)
      load localPendingChanges     // we are merging in the Breeze entityManager remote data with localPendingChanges
      Savedata                     // we are online and we have pending changes, so we should sync everything back to the remoteDb as soon as possible
  if(offline)
    load localDb
    if(localPendingChanges)
      load localPendingChanges     // we are merging in the Breeze entityManager local data with localPendingChanges

SaveData
  if(online)
    save remoteDb
    clear localPendingChanges      // until we are online there is no need to keep localPendingChanges
    LoadData                       // we are loading data from remoteDb to update our localDb to the latest version
  if(offline)
    save localPendingChanges       // we are saving only the changes to localstorage

您如何看待这种方法?这是一团糟吗?好吗? 那么多用户场景中的并发问题呢?

2 个答案:

答案 0 :(得分:3)

这似乎是合理的,不太确定为什么你需要两个localStorage键。维护localStorage中放置的每个实体的entityState(未修改,修改,添加,删除),以便您可以始终“提取”(请参阅​​EntityManager.getEntities方法)只是来自任何本地副本的挂起更改。那么为什么不在关闭应用程序之前将整个entityManager状态保存到localStorage。

对于并发问题,您绝对应该在每个entityType上设置并发属性。只要存在,并且您通过实体框架进行保存,breeze将在保存期间检测到任何乐观并发冲突并抛出异常。显然,在这种异常之后,您已确定应用程序的正确行为。

我确定你已经看过了,但QueryOptions.MergeStrategy(PreserveChanges,OverwriteChanges)对于在任何查询后保留或覆盖本地机器上的数据非常有帮助。

答案 1 :(得分:2)

我认为您将本地更改保留在与服务器同步的位置是正确的。我已经解决了这个问题几个月了,并提出了一个看起来非常类似于版本控制系统的东西,其中一组中的一个键中的所有数据都被单独版本化。您可以将更改从服务器下载到本地数据库,如果通过冲突解决回调双方更改了它们,它将处理。

目前我对Knockout知之甚少,但是库本身并不依赖于任何单独的项目,而是在Node.JS,Dojo和jQuery中传递测试用例。它有一个超级紧密的API(.get,.set,.feed(用于从服务器加载下载的数据)和.getFirst(用于访问需要上传的内容)。

网址位于https://github.com/forbesmyester/SyncIt,它还有相当全面的演示和文档。