Как узнать примерное положение события в очереди в очереди событий Javascript Engine?
Предположим, у нас есть поток событий, которые генерируются и помещаются в очередь в доступной очереди событий движка Javascript. Существует ли какой-либо метод или лучшая отраслевая практика для оценки позиции конкретного события, помещенного в очередь?
Любое понимание этой темы высоко ценится.
1 ответ
Не существует стандартного способа просмотра очереди цикла событий программно. Единственный способ узнать, где событие может находиться в этой очереди, - это узнать, когда оно было добавлено относительно других событий, и узнать, какие типы событий идут в цикле событий.
В современных средах JavaScript имеет два вида очередей "сделать это позже": основной цикл обработки событий (содержащий "макрозадачи") и второй цикл запуска в конце каждой задачи основного цикла для любых "микрозадач", запланированных этой макрозадачей. В браузерах есть и третье, requestAnimationFrame
(RAF), который отделен от циклов событий (пока еще координируется с ними).
Большинство обработчиков событий, с которыми вы знакомы, называются "макрозадачами" в основном цикле событий. setTimeout
, События DOM и т. Д.
Обработчики завершения Promise называются "микрозадачами" сразу после макрозадачи, в которой они поставлены в очередь (поэтому они выполняются перед следующей макрозадачей, если она есть, даже если она была поставлена в очередь первой).
Обратные вызовы RAF вызываются между макрозадачами, когда браузер собирается перерисовать, опять же, даже если следующая макрозадача была поставлена в очередь до requestAnimationFrame
обратный звонок был.
Пример:
function run() {
requestAnimationFrame(function() {
log("RAF 1");
});
function log(msg) {
var p = document.createElement("pre");
p.appendChild(document.createTextNode(msg));
document.body.appendChild(p);
}
setTimeout(function() {
log("timeout 1");
Promise.resolve().then(function() {
log("resolution 2 -- before timeout 2");
});
}, 0);
setTimeout(function() {
log("timeout 2");
requestAnimationFrame(function() {
log("RAF 2");
});
}, 0);
setTimeout(function() {
log("timeout 3");
requestAnimationFrame(function() {
log("RAF 3");
});
}, 0);
Promise.resolve().then(function() {
log("resolution 1");
});
}
function tick() {
document.body.innerHTML = "";
run();
setTimeout(tick, Math.random() * 800);
}
tick();
pre {
margin-top: 0;
margin-bottom: 0;
}
Если вы посмотрите это достаточно долго, вы заметите, что, хотя тайм-ауты и разрешения обещаний всегда находятся в одном и том же порядке, обратные вызовы RAF выполняются среди них в разное время (обычно в конце, но не всегда).
Также обратите внимание, как разрешения обещаний (микрозадачи) выполняются перед следующей макрозадачей.