разрешены чтения indexeddb / localforage из синхронного буфера? - PullRequest
0 голосов
/ 02 марта 2019

Взяв следующий псевдокод

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:-

  • A.Гарантированно отображается «бар»

  • B.Гарантированное отображение «неопределено»

  • C.Не определено

т.е. даже если запись на диск асинхронная, будет ли разрешено синхронное чтение из внутреннего буфера в indexeddb и / или localforage?

1 Ответ

0 голосов
/ 03 марта 2019

Я взглянул на драйвер indexFDB localForage на https://github.com/localForage/localForage/blob/master/src/drivers/indexeddb.js. Я не вижу никакой буферизации.Таким образом, getItem ничего не может извлечь из некоторого буфера.

Более конкретно, снова обращаясь к источнику localForage, я вижу, что setItem и getItem являются основными обертками обещаний вокруг транзакций indexedDB,Эти оболочки разрешаются после завершения транзакций.Это говорит мне, что indexedDB - это то, что управляет неблокирующим поведением, а не localForage.

Итак, поскольку indexedDB отвечает, это означает, что мы можем посмотреть на поведение indexedDB, чтобы помочь ответить на ваш вопрос.Мы выдаем две транзакции, каждая с запросом.Первая - это транзакция чтения-записи от setItem, а вторая - транзакция только для чтения из getItem.

Обычно транзакции могут перекрываться.Например, у вас может быть 100 транзакций только для чтения, запущенных одновременно.Однако транзакции readwrite блокируют другие транзакции для обеспечения целостности данных.транзакции readwrite не могут перекрываться.

Это немного усложняется тем фактом, что вы можете запускать и забывать вызовы.Вы можете инициировать две транзакции одновременно, не дожидаясь начала второй до тех пор, пока не завершится первая.Обратите внимание на разницу между началом выполнения чего-либо и фактическим его выполнением.

Итак, глядя на ваш код, setItem('foo', 'bar') запускает транзакцию readwrite, а getItem ('foo') запускает транзакцию только для чтения.Вы не ждете, пока обертка обещания транзакции readwrite завершится, прежде чем начинать транзакцию только для чтения.

Хотя это действительно неблокирующий подход на поверхности, он все еще технически блокируется на уровне indexedDB, потому что readonlyтранзакция будет блокировать (ждать, на неопределенное время) предыдущую транзакцию чтения-записи в том же хранилище объектов для урегулирования.

И это, как мне кажется, вызывает путаницу.Поскольку мы знаем, что транзакция только для чтения была запущена после того, как была запущена операция чтения, мы знаем, что технически транзакция только для чтения всегда будет разрешаться только после транзакции чтения и записи, поскольку она не может быть разрешена ни до нее, ни одновременно с ней.

Таким образом, вы можете сказать, что ответ будет A. Поскольку транзакция только для чтения должна ждать завершения транзакции чтения-записи.Он не определен на уровне обещаний localForage, но определен на уровне транзакций indexedDB.

Более подробное техническое описание см. В спецификации https://www.w3.org/TR/IndexedDB-2/#transaction-construct

Вот соответствующий раздел (выделено мое):

Если несколько транзакций чтения / записи пытаются получить доступ к одному и тому же хранилищу объектов (т. Е. Если они имеют перекрывающуюся область видимости), то созданная сначала транзакция должна быть транзакцией, которая получает доступ к объекту.хранить в первую очередь.В соответствии с требованиями предыдущего параграфа это также означает, что это единственная транзакция, которая имеет доступ к хранилищу объектов до тех пор, пока транзакция не будет завершена.

Любая транзакция, созданная после транзакции чтения / записи, должнасм. изменения, записанные транзакцией чтения / записи. Таким образом, если создается транзакция чтения / записи A, а затем создается другая транзакция B, и две транзакции имеют перекрывающиеся области действия, то B должен видеть любые изменениясделано для любых хранилищ объектов, которые являются частью этой перекрывающейся области.Из-за требований предыдущего параграфа это также означает, что транзакция B не имеет доступа ни к каким хранилищам объектов в этой перекрывающейся области, пока транзакция A не будет завершена.

В общем, приведенные выше требования означают, что любыеТранзакция, имеющая перекрывающуюся область с транзакцией чтения / записи и созданная после этой транзакции чтения / записи, не может выполняться параллельно с этой транзакцией чтения / записи.

...