任务和微任务之间的区别很重要,因为IndexedDB事务跨任务提交,但不提交微任务。在承诺包装IndexedDB代码时,这是有问题的,因为在Firefox (可能还有其他浏览器)中,承诺解析不会在微任务中发生,所以您的事务将提交。
解决这个问题的方法是使用使用微任务的第三方承诺实现。lie是其中的一个库,它将微任务问题抽象为另一个名为immediate的库,该库使用MutationObserver生成微任务。
大多数情况下,效果很好。但是在网络工作者中,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);
});
};当我正常运行的时候,效果很好。当我在Worker中运行它时,它会失败,因为在调用immediate时,在回调运行之前,事务会提交。在Chrome和Firefox中都会出现这种情况。
到目前为止,我想出了两种解决方案:
这两种选择都非常不稳定。所以我问你,Stack溢出,你知道如何在Web工作人员内部排队处理微任务吗?
发布于 2017-03-13 12:35:20
简短的回答:你不能在网络工作者身上这么做
很长的答案:没有实际的微任务api,只有黑客试图模拟他们。不幸的是,那些工作最好的(变异观察者)主要与DOM有关,所以它们只能在主线程中使用,而不是在web工作者中。话虽如此,但对于美洲开发银行来说,这或许是有意义的,并承诺规范官方关系,但我不确定是否真的有这样的承诺,因为承诺和美洲开发银行来自不同群体。实际上,浏览器厂商可能会对web工作者进行真正的微任务api,因为大多数反对意见都与不小心将主线程冲洗掉有关。
https://stackoverflow.com/questions/42660581
复制相似问题