Web Worker 中的微任务

Microtasks inside Web Workers

任务和微任务之间的区别很重要,因为 IndexedDB transactions commit across tasks, but not microtasks。在 Promises 中包装 IndexedDB 代码时,这是有问题的,因为在 Firefox(以及其他浏览器)中,promise 解析不会发生在微任务中,因此您的事务将提交。

这个问题的解决方案是使用使用微任务的第三方承诺实现。 lie is one of those libraries, and under the hood it abstracts the microtask problem into another library called immediate,它使用 MutationObserver 生成微任务。

大多数情况下效果很好。但是在 Web Worker 中, MutationObserver 不存在,所以这个技巧是行不通的。 Here's an example of the problem in an easily-runnable GitHub repo. 基本上我有这个代码:

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 时提交,在回调 运行s 之前。 Chrome 和 Firefox 都会发生这种情况。

到目前为止,我想到了两个解决方案:

  1. 不要使用承诺,回到回调地狱
  2. 使用同步解析的承诺

这两个选项都非常不令人满意。所以我问你,Stack Overflow,你知道在 Web Worker 中对微任务进行排队的方法吗?

简短回答:你不能在网络工作者中做到这一点

长答案:没有实际的微任务 api,只有尝试模拟它们的 hack。不幸的是,最有效的(突变观察者)主要与 DOM 有关,因此它们仅在主线程中可用,而不在网络工作者中可用。话虽这么说,这对 IDB 和承诺标准化官方关系可能有意义,但我不确定是否真的有一个具体说明,因为承诺和 IDB 来自不同的团体。实际上,浏览器供应商可能对在 Web Worker 内部执行真正的微任务 api 有一些吸引力,因为大多数反对意见都与意外地处理主线程有关。