从多个javascript线程访问IndexedDB [英] Accessing IndexedDB from multiple javascript threads
问题描述
概述:
我试图通过从网页和网络工作者访问IndexedDB来避免竞争条件。
Overview: I am trying to avoid a race condition with accessing an IndexedDB from both a webpage and a web-worker.
设置:
当用户使用网站时,将项目保存到本地IndexedDB的网页。每当用户将数据保存到本地数据库时,记录就会被标记为未发送。
Setup: Webpage that is saving items to the local IndexedDB as the user works with the site. Whenever a user saves data to the local DB the record is marked as "Unsent".
从IndexedDB中提取数据的Web工作者后台线程,将其发送到服务器,一旦服务器收到它,将IndexedDB中的数据标记为已发送。
Web-worker background thread that is pulling data from the IndexedDB, sending it to the server and once the server receives it, marking the data in the IndexedDB as "Sent".
问题:
由于访问IndexedDB是异步的,我不能保证用户不会在web-worker将其发送到服务器的同时更新记录。时间表如下所示:
Problem: Since access to the IndexedDB is asynchronous, I can not be guaranteed that the user won't update a record at the same time the web-worker is sending it to the server. The timeline is shown below:
- 网络工作者从数据库获取数据并将其发送到服务器
- 当传输发生时,用户更新数据将其保存到数据库。
- Web工作者从服务器获取响应,然后将数据库更新为已发送
- 现在DB中的数据尚未发送到服务器但标记为已发送
- Web-worker gets data from DB and sends it to the server
- While the transfer is happening, the user updates the data saving it to the DB.
- The web-worker gets the response from the server and then updates the DB to "Sent"
- There is now data in DB that hasn't been sent to the server but marked as "Sent"
解决方案失败:
从服务器获得响应后,我可以重新检查行以查看是否有任何更改。但是我仍然留有一个小窗口,可以将数据写入数据库并且它永远不会被发送到服务器。
Failed Solution: After getting the response from the server, I can recheck to row to see if anything has been changed. However I am still left with a small window where data can be written to the DB and it will never be sent to the server.
示例:
服务器之后说数据已保存,然后:
Example: After server says data is saved, then:
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() }
});
其他注意事项:
有一个同步api根据W3规范,但还没有人实现它,因此无法使用(http://www.w3.org/TR/IndexedDB/#sync-database)。 sync api旨在供网络工作者使用,以避免我假设的这种情况。
Other notes: There is a sync api according to the W3 spec, but no one has implemented it yet so it can not be used (http://www.w3.org/TR/IndexedDB/#sync-database). The sync api was designed to be used by web-workers, to avoid this exact situation I would assume.
对此的任何想法都将非常感激。已经工作了大约一个星期,并且无法提出任何可行的方法。
Any thoughts on this would be greatly appreciated. Have been working on it for about a week and haven't been able to come up with anything that will work.
推荐答案
我我觉得我现在找到了解决这个问题的方法。并不像我想的那样干净,但似乎是线程安全的。
I think I found a work around for this for now. Not really as clean as I would like, but it seems to be thread safe.
每当我更新数据时,我都会将datetime存储到LastEdit字段中。
来自网络工作者,我正在向浏览器发帖子。
I start by storing the datetime into a LastEdit field, whenever I update the data. From the web-worker, I am posting a message to the browser.
self.postMessage('UpdateDataSent#' + data.ID + '#' + data.LastEdit);
然后在浏览器中我更新我发送的标志,只要上次编辑日期没有改变。
Then in the browser I am updating my sent flag, as long as the last edit date hasn't changed.
// 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,我就可以把它扔掉。
Since this is all done in a transaction in the browser side, it seems to work fine. Once the browsers support the Sync API I can throw it all away anyway.
这篇关于从多个javascript线程访问IndexedDB的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!