概述: 我试图通过从网页和网络工作者访问IndexedDB来避免竞争条件。
设置: 当用户使用站点时将项目保存到本地IndexedDB的网页。每当用户将数据保存到本地数据库时,记录就会标记为“未发送”。
Web-worker后台线程,它从IndexedDB中提取数据,将其发送到服务器,一旦服务器收到它,就将IndexedDB中的数据标记为“已发送”。
问题: 由于对IndexedDB的访问是异步的,因此我无法保证用户不会在Web工作者将其发送到服务器的同时更新记录。时间表如下所示:
解决方案失败: 从服务器获得响应后,我可以重新检查行以查看是否有任何更改。但是我仍然留有一个小窗口,可以将数据写入数据库,并且永远不会将数据发送到服务器。
实施例: 服务器说保存数据后,然后:
IndexedDB.HasDataChanged(
function(changed) {
// Since this is async, this changed boolean could be lying.
// The data might have been updated after I checked and before I was called.
if (!changed){
IndexedDB.UpdateToSent() }
});
其他说明: 根据W3规范有一个sync api,但还没有人实现它,因此无法使用它(http://www.w3.org/TR/IndexedDB/#sync-database)。 sync api旨在供网络工作者使用,以避免我假设的这种情况。
对此的任何想法将不胜感激。已经工作了大约一个星期,并且无法提出任何可行的方法。
答案 0 :(得分:2)
我想我现在找到了解决这个问题的方法。不像我想的那么干净,但似乎是线程安全的。
每当我更新数据时,我都会将datetime存储到LastEdit字段中。 我从网络工作者那里向浏览器发帖子。
self.postMessage('UpdateDataSent#' + data.ID + '#' + data.LastEdit);
然后在浏览器中,我正在更新我发送的标志,只要最后一个编辑日期没有改变。
// Get the data from the DB in a transaction
if (data.LastEdit == lastEdit)
{
data.Sent = true;
var saveStore = trans.objectStore("Data");
var saveRequest = saveStore.put(data);
console.log('Data updated to Sent');
}
由于这一切都是在浏览器端的事务中完成的,所以它似乎工作正常。一旦浏览器支持Sync API,无论如何我都可以把它扔掉。
答案 1 :(得分:0)
答案 2 :(得分:0)
旧线程,但使用事务将解决失败的解决方案方法。即事务只需要检查在发送之后 索引IndexDB中的数据没有更改的检查,如果没有更改,则将其标记为已发送。如果进行了更改,则交易将结束而无需写入。