В чем разница при выполнении обратного вызова события «click», инициируемого пользователем и запускаемого программно? - PullRequest
1 голос
/ 08 октября 2019

Я просматривал статью Джейка Арчибальда о задачах, микрозадачах и т. Д. В его примере мы видим, что «журналы консоли» печатаются в определенном порядке для события щелчка, основанного на пользователе, и другой порядок события щелчка запускается программно. Я спрашиваю, не мог бы кто-нибудь объяснить это более подробно о выполнении обратного вызова по клику в этих двух случаях.

HTML

<div class="outer-test"><div class="inner-test"></div></div>

CSS

.outer-test {
  background: #D4D4D4;
  padding: 25px;
  width: 92px;
  margin: 0 auto;
}

.inner-test {
  background: #ADADAD;
  padding: 46px;
  width: 0;
}

JS (Первый случай)

var outer = document.querySelector('.outer-test');
var inner = document.querySelector('.inner-test');


new MutationObserver(function() {
  console.log('mutate');
}).observe(outer, {
  attributes: true
});


function onClick() {
  console.log('click');

  setTimeout(function() {
    console.log('timeout');
  },0);

  Promise.resolve().then(function() {
    console.log('promise');
  });

  outer.setAttribute('data-random', Math.random());
}


inner.addEventListener('click', onClick);
outer.addEventListener('click', onClick);


JS (Второй случай)

var outer = document.querySelector('.outer-test');
var inner = document.querySelector('.inner-test');


new MutationObserver(function() {
  console.log('mutate');
}).observe(outer, {
  attributes: true
});


function onClick() {
  console.log('click');

  setTimeout(function() {
    console.log('timeout');
  },0);

  Promise.resolve().then(function() {
    console.log('promise');
  });

  outer.setAttribute('data-random', Math.random());
}


inner.addEventListener('click', onClick);
outer.addEventListener('click', onClick);

inner.click();  //<======== 

Для справки: https://jakearchibald.com/2015/tasks-microtasks-queues-and-schedules/

1 Ответ

0 голосов
/ 08 октября 2019

.click () заставляет событие отправлять синхронно, поэтому скрипт, который вызывает .click (), все еще находится в стеке между обратными вызовами.

Он просматривает ответ, но этов основном это. Не собираясь притворяться, что я полностью понимаю детали, но когда я читаю это: поскольку щелчок запускается изнутри JavaScript в том же «фрейме», что и код, который настраивает прослушиватели событий И запускает событие таким образом, синхронные обратные вызовызапускаются сразу после этого, потому что это не позволяет проверить очередь микрозадачи на наличие мутаций.

В первом случае «установка» завершается, а этот «кадр» заканчивается. Так что, только нажав в браузере, что-то срабатывает, что затем произойдет в другом кадре (асинхронно), и так как никакой другой «кадр» не запускается в этот момент, он идет вперед и сначала проверяет очередь на наличие микрозадач на предмет мутации.

Приведенное выше правило гарантирует, что микрозадачи не прерывают JavaScript, который выполняется в середине.

И это, вероятно, является причиной того, почему этого не делается, что имеет смысл, так как все этооднопоточным (вы знаете, вроде), что имеет смысл позволить этому «кадру» закончить.

Таким образом, причуды действительно в том, что запуск события запрограммированно вынуждает все это в синхронную землю.

...