任务和微型掩码之间的区别很重要,因为索引dexeddb交易跨任务,而不是微型施法。在Promises中包装索引DB代码时,这是有问题的,因为在Firefox(也许还有其他浏览器)中,Promise解决方案不会在Microtask中发生,因此您的交易将提交。
解决此问题的解决方案是使用使用MicroTasks的第三方承诺实现。lie
是其中一个库之一,在引擎盖下,它将微型箱问题抽象到另一个名为immediate
的库中,该库使用MutationObserver
生成Microtasks。
大部分时间都很好。但是在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
时进行的交易会进行。这发生在铬和firefox中。
截至目前,我已经想到了两种解决方案:
- 不要使用承诺,回到回调地狱
- 使用同步分辨率的承诺
这两种选项都高度毫无影利。所以我问你,堆叠溢出,您知道一种在网络工作人员内排队微型掩体的方法吗?
简短答案:您不能在Web Worker中做到这一点
长答案:没有实际的Microtask API,只有黑客可以尝试模拟它们。不幸的是,那些最有效的(突变观察者)主要与DOM有关,因此它们仅在主线程中可用。话虽如此,对于IDB来说,这可能是有意义的,并承诺将正式关系标准化,我不确定是否真的指出了一个人,因为承诺和IDB来自不同的群体。实际上,浏览器供应商可能会在Web工作人员内部进行真实的微型API,因为大多数反对意外的反对与意外构成主线程有关。