indexeddb/localforage 读取是从同步缓冲区解析的吗?

are indexeddb/localforage reads resolved from a synchronous buffer?

采取如下伪代码

localforageStore.setItem('foo', 'bar')
    .then(console.log('foo is persisted to disk')); 
localforageStore.getItem('foo')
    .then(v => console.info('foo is '+v));   // A, B or C? 

是console.info:-

即即使写入磁盘是异步的,是否会从 indexeddb 的内部缓冲区解析同步读取 and/or localforage?

我查看了 https://github.com/localForage/localForage/blob/master/src/drivers/indexeddb.js 上的 localForage indexedDB 驱动程序。我没有看到任何缓冲。因此,getItem 无法从某个缓冲区中获取任何内容。

更具体地说,再次查看 localForage 源代码,我可以看到 setItemgetItem 是 indexedDB 事务的基本承诺包装器。这些包装器在事务完成时解析。这告诉我 indexedDB 是控制非阻塞行为的,而不是 localForage。

因此,由于 indexedDB 负责,这意味着我们可以查看 indexedDB 行为来帮助回答您的问题。我们正在发出两笔交易,每笔交易都有一个请求。第一个是来自 setItem 的读写事务,第二个是来自 getItem.

的只读事务

通常,事务可以重叠。例如,您可以同时拥有 100 个全部 运行ning 只读事务。但是,读写事务会阻塞其他事务以确保数据完整性。读写事务不能重叠。

这变得有点复杂,因为您可以触发并忘记调用事物。您可以同时启动两个事务,而不必等到第一个事务完成后再启动第二个事务。请注意开始 运行 某事与实际将其视为 运行ning.

之间的区别

因此,查看您的代码,setItem('foo', 'bar') 启动一个读写事务,而 getItem('foo') 启动一个只读事务。在启动只读事务之前,您没有等待读写事务承诺包装器解决。

虽然这在表面上确实是一种非阻塞方法,但它在 indexedDB 层内在技术上仍然是阻塞的,因为只读事务将阻塞(等待,无限期地)同一对象存储上的先前读写事务解决。

我认为这就是造成混淆的原因。因为我们知道只读事务是在读写启动之后启动的,所以我们知道只读事务在技术上总是只在读写事务之后解析,因为它不可能在它之前解析,也不能与它同时解析。

因此,你可以说答案是A。因为只读事务必须等待读写事务完成。它在 localForage promise 层是不确定的,但在 indexedDB 事务层是确定的。

https://www.w3.org/TR/IndexedDB-2/#transaction-construct

查看规范以获得更多技术解释

这是一个相关部分(重点是我的):

If multiple read/write transactions are attempting to access the same object store (i.e. if they have overlapping scope), the transaction that was created first must be the transaction which gets access to the object store first. Due to the requirements in the previous paragraph, this also means that it is the only transaction which has access to the object store until the transaction is finished.

Any transaction created after a read/write transaction must see the changes written by the read/write transaction. So if a read/write transaction, A, is created, and later another transaction B, is created, and the two transactions have overlapping scopes, then B must see any changes made to any object stores that are part of that overlapping scope. Due to the requirements in the previous paragraph, this also means that the B transaction does not have access to any object stores in that overlapping scope until the A transaction is finished.

Generally speaking, the above requirements mean that any transaction which has an overlapping scope with a read/write transaction and which was created after that read/write transaction, can’t run in parallel with that read/write transaction.