2017-03-07 49 views
10

任务与微任务之间的区别很重要,因为IndexedDB transactions commit across tasks, but not microtasks。将IndexedDB代码包装在Promise中时,这是有问题的,因为在Firefox(也可能是其他浏览器)中,承诺解决方案不会发生在微任务中,因此您的事务将提交。网络工作者内部的微任务

此问题的解决方案是使用使用microtasks的第三方承诺实现。 lie是其中的一个库,在它的引擎之下,它将microtask问题抽象为另一个名为immediate的库,该库使用MutationObserver生成微任务。

这在大多数情况下效果很好。但是在网络工作者中,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. 使用的承诺与同步分辨率

这两项的选项非常不重要。所以我问你,堆栈溢出,你知道一个在Web Worker中排队microtasks的方法吗?

+0

解析器中同步执行回调的承诺没有听起来那么糟糕。您只需要确保:a)决议本身是异步触发的(或至少在回合结束时); b)您可以信任触发决议的一方 – Bergi

+0

关于“macrotasks”的问题谈话的开头句,但此后是“微型任务”。这是故意的,如果可以,请你解释一下吗? –

+0

@Bergi你知道一个图书馆的行为方式,你描述的方式? – dumbmatter

回答

5

简短的回答:你不能这样做,在一个网络工作者

长的答复:没有实际microtask API,目前只有黑客试图模仿他们。不幸的是,那些效果最好的(突变观察者)主要与DOM有关,因此它们只能在主线程中使用,而不能在web worker中使用。据说这对于美洲开发银行来说可能是有意义的,并且承诺将正式关系标准化,但我不确定实际上是否有承诺和IDB来自不同的团体。实际上,浏览器供应商可能会对网络工作者内部的一个真正的微任务api产生一定的影响,因为大多数反对意见都意外地处理了主线程。

+0

https://github.com/inexorabletash/indexeddb-promises/标准化IDB和诺言的工作,但似乎没有太多的牵引力(虽然我不是浏览器开发者,所以希望我错了关于那个)。 – dumbmatter