Различие между задачами и микротомами важно, потому что транзакции IndexedDB совершают задачи, но не микротовары. Это проблематично при обертке кода IndexedDB в Promises, потому что в Firefox (и, возможно, в других браузерах) обещание не выполняется в микрозадаче, поэтому транзакция будет зафиксирована.
Решение этой проблемы заключается в использовании стороннего обещания, в котором используются микротовары. lie
является одной из этих библиотек, и под капотом он абстрагирует проблему микрозадачи в другой библиотеке под названием immediate
, который использует MutationObserver
для создания микротоков.
Это работает отлично, большую часть времени. Но в Web Worker MutationObserver
не существует, так что трюк не будет работать. Вот пример проблемы в легко исполняемом репозитории GitHub. В основном у меня есть этот код:
var immediate = require('immediate');
var openRequest = indexedDB.open('firefox-indexeddb-promise-worker-test');
openRequest.onupgradeneeded = function() {
var db = openRequest.result;
var store = db.createObjectStore('whatever', {keyPath: 'id'});
store.put({id: 1});
store.put({id: 2});
store.put({id: 3});
};
function get(tx, id, cb) {
immediate(function () {
var req = tx.objectStore('whatever').get(id);
req.onsuccess = function (e) {
console.log('got', e.target.result);
if (cb) {
cb(null, e.target.result);
}
};
req.onerror = function (e) {
console.error(e.target.error);
if (cb) {
cb(e.target.error);
}
};
});
}
openRequest.onsuccess = function() {
var db = openRequest.result;
var tx = db.transaction('whatever');
tx.oncomplete = function () {
console.log('tx complete');
};
get(tx, 1, function () {
get(tx, 2);
});
};
Когда я запускаю это нормально, он работает нормально. Когда я запускаю его в Web Worker, он терпит неудачу, потому что транзакция завершается, когда вызывается immediate
, прежде чем обратный вызов будет запущен. Это происходит как в Chrome, так и в Firefox.
На данный момент я подумал о двух решениях:
- Не используйте Promises, вернитесь к обратному аду.
- Используйте promises с синхронным разрешением
Оба эти параметра сильно не распознаются. Итак, я спрашиваю вас, "Переполнение стека", знаете ли вы, как настроить очередь на микрозадания внутри веб-рабочего?