indexedDb-使用两个独立的密钥(本地和服务器ID/联机和脱机)进行保存/更新
indexedDb - saving/updating with two independent keys (local and server IDs / online and offline)
我想写一个Angular模块,它本地保存数据(使用IndexedDB),并通过RESTful服务将数据与服务器数据同步。
我已经为此构建了一个基本的基础,可以将数据获取到服务器并将其放入IndexedDB中。
因为web应用程序也必须在脱机模式下运行,所以我选择为对象存储使用两个键。自动递增的本地ID和服务器上条目的ID。
服务器不知道本地ID,如果无法将本地数据条目传输到服务器,则本地数据条目可能不知道服务器ID
当我为服务器ID定义一个唯一索引时,如果服务器ID已经存在并且更新过程停止,则本地条目不会得到更新。
有没有办法通过IDB API直接做到这一点?
我发现了一个类似的问题,但使用一个简单的游标和游标更新解决方案,就不可能将新数据从服务器插入到本地数据库:Indexeddb-通过索引键更新记录
我找到了一种方法。我将处理本地数据(带有本地id)和服务器数据(没有本地id,因为服务器不知道)。
然后,我将使用IDBObjectStore.put
更新本地数据,并检查来自服务器的数据(服务器id已设置,但没有本地id)是否已通过单独的IDBIndex.openCursor
调用保存在本地。如果找到具有给定serverId的本地数据,则会添加一个带有put IDBObjectStore.put
的新条目,如果找到该条目,则会使用服务器数据更新该条目上的光标(旧的localId将被保留)。
// var _db => connected database
// filter the data that came from the server (no local id defined but server id is)
var serverData = [];
for (var i = 0; i < data.length; i++) {
if (data[i]._localId === undefined && data[i].serverId !== undefined && data[i].serverId !== null) {
// remove the server data object and add it to the server data array
serverData = serverData.concat(data.splice(i, 1));
i--;
}
}
var transaction = _db.transaction(_storageName, 'readwrite');
transaction.oncomplete = function() {
// do something on completion
};
transaction.onerror = function(e) {
// do something when an error occurs
};
var objectStore = transaction.objectStore(_storageName);
// Add local data to the database (no server id)
// local id can be existing or not (new entry)
for (var i = 0; i < data.length; i++) {
objectStore.put(data[i]).onsuccess = function(e) {
// do something when successfully added
};
}
// Add data from the server to the database
var index = objectStore.index('serverId'); // server id index for searching
// go through all data from the server
for (var i = 0; i < serverData.length; i++) {
(function(){
var serverItem = serverData[i];
// search for an existing entry in the local database
var checkRequest = index.openCursor(IDBKeyRange.only(serverItem.serverId));
checkRequest.onsuccess = function (e) {
var cursor = e.target.result;
// If item was not found in local indexedDB storage...
if (cursor === null) {
// add new item to storage
this.source.objectStore.put(serverItem).onsuccess = function(e) {
// do something when successfully added
};
// Item was found locally
} else {
var dbItem = cursor.value;
// set local id of the added item to the one from the old local entry
serverItem.localId = dbItem.localId;
// update found local entry with the one from the server
cursor.update(serverItem).onsuccess = function(e) {
// do something on success
};
}
};
})();
}
可能有一个更优雅的解决方案,但这是我想出的第一个,有效的。如果有任何改进或更好的解决方案,我将不胜感激。
相关文章:
- 如何传递id列表's在MVC中向服务器发出AJAX请求
- 如何将url id映射到服务器上的内容
- Ember更新id在服务器上持久化后
- 为客户端和服务器上的对象生成唯一 ID
- 使用科尔多瓦在我的网络服务器上存储 GCM ID 不起作用
- 如何将数据(如用户 ID)传递给 Web 工作人员,以便从服务器获取其他推送通知数据
- 跨多个客户端和服务器生成真正的全局唯一 ID
- 如何在客户端获取服务器删除/更新收集项的 ID
- redips.拖动 获取行 ID 删除并发送到服务器
- Ember-将模型id从路由中取出并发布到服务器
- indexedDb-使用两个独立的密钥(本地和服务器ID/联机和脱机)进行保存/更新
- 如何在 html 元素中呈现服务器控件客户端 ID
- 客户端到服务器端的google analytics MP客户端ID
- 与控件ID关联的访问服务器控件
- 从服务器获取Angular工厂中新建资源的ID
- 获取具有相同服务器ID的多个userControl的clientID
- 按客户端 ID 服务器端 asp.net 获取禁用的文本框值
- 在服务器上使用客户端(会话)id作为键的流星字典
- 在javascript函数中作为参数传递服务器端控件的客户端ID
- 在dropzone.js中分配文件服务器id