IndexedDB transactions commit across tasks, but not microtasks은 태스크와 마이크로 태스크의 구분이 중요합니다. 이는 Firefox (및 다른 브라우저)에서 약속 해상도가 마이크로 태스크에서 발생하지 않기 때문에 Promise에서 IndexedDB 코드를 래핑 할 때 문제가되므로 트랜잭션이 커밋됩니다.웹 작업자 내부의 마이크로 태스크
이 문제에 대한 해결책은 마이크로 태스크를 사용하는 타사 약속 구현을 사용하는 것입니다. lie
은 그러한 라이브러리 중 하나이며 마이크로 후드 문제는 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);
});
};
정상적으로 실행하면 정상적으로 작동합니다. 웹 작업자에서 실행하면 콜백이 실행되기 전에 immediate
이 호출 될 때 트랜잭션이 커밋되기 때문에 실패합니다. 이 문제는 Chrome과 Firefox에서 발생합니다.
는 지금, 나는이 개 솔루션을 생각했습니다
- 동기 해상도
그 모두 지옥에게
리졸버 내에서 콜백을 동기 실행하는 약속은 소리가 나쁘지 않습니다. a) 해상도 자체가 비동기 적으로 (또는 최소한 턴이 끝날 때) 트리거되고 b) 해결을 트리거하는 당사자를 신뢰할 수 있는지 확인해야합니다. – Bergi
"매크로 태스크"에 대한 질문의 시작 문장, 그러나 그 후에 "microtasks". 이것은 의도적입니까? 그렇다면 설명해주십시오. –
@Bergi는 당신이 설명하는대로 행동하는 라이브러리에 대해 알고 있습니까? – dumbmatter