Как узнать примерное положение события в очереди в очереди событий 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 выполняются среди них в разное время (обычно в конце, но не всегда).

Также обратите внимание, как разрешения обещаний (микрозадачи) выполняются перед следующей макрозадачей.

Другие вопросы по тегам