【问题标题】:Microtasks inside Web WorkersWeb Workers 中的微任务
【发布时间】:2017-03-07 23:58:07
【问题描述】:

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

解决这个问题的方法是使用使用微任务的第三方 Promise 实现。 lie 就是其中一个库,在底层,它将微任务问题抽象到另一个名为 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 时事务提交。这在 Chrome 和 Firefox 中都会发生。

到目前为止,我已经想到了两种解决方案:

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

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

【问题讨论】:

  • 在解析器中同步执行回调的承诺并不像听起来那么糟糕。您只需要确保 a) 决议本身是异步触发的(或至少在回合结束时)并且 b) 您可以信任触发决议的一方
  • 问题的开始句谈论“宏任务”,但随后是“微任务”。这是故意的吗?如果是,请解释一下?
  • @Bergi 你知道一个库的行为方式和你描述的一样吗?
  • @Roamer-1888 这是一个错字,谢谢。我相信“任务”和“宏任务”在这种情况下是同义词,而“微任务”是不同的。
  • @dumbmatter I had written one myself,但我想您可以使用任何允许您提供自己的调度程序的方法

标签: javascript promise indexeddb web-worker


【解决方案1】:

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

长答案:没有实际的微任务 api,只有黑客尝试模拟它们。不幸的是,效果最好的那些(突变观察者)主要与 DOM 有关,因此它们仅在主线程中可用,而在 web worker 中不可用。话虽这么说,这对 IDB 和承诺标准化官方关系可能是有意义的,但我不确定是否真的有一个作为承诺和 IDB 来自不同群体的规定。实际上,浏览器供应商可能会在 Web Worker 内部做一个真正的微任务 API,因为大多数反对意见都与不小心占用主线程有关。

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-12-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-28
相关资源
最近更新 更多