Последовательность выполнения обратного вызова наблюдателя касания, прокрутки и пересечения

#javascript #google-chrome #scroll #touch #intersection-observer

#javascript #google-chrome #прокрутка #касание #наблюдатель пересечения

Вопрос:

Этот вопрос касается последовательности выполнения обратного вызова touch, scroll и intersection observer.

У меня есть простое мобильное веб-приложение, которое имеет прокручиваемый список, где каждый элемент имеет высоту 100 пикселей, и у меня есть наблюдатель пересечения, размещенный на видовом экране, но с верхним полем -100 пикселей ( rootMargin: "-100px 0px 0px 0px" ).

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

Наблюдатель пересечения выглядит следующим образом:

 const io = new IntersectionObserver(viewportBottomObserverCallback, {
  root: null,
  rootMargin: "-100px 0px 0px 0px",
  threshold: [0, 1]
})
  

У меня есть обработчик touchmove, обработчик прокрутки и обратный вызов наблюдателя пересечения.

Теперь, как только я касаюсь и провожу пальцем вверх, я вижу последовательное поведение при выполнении этих обработчиков / обратных вызовов. Сначала onTouchMove вызывается, затем onScroll вызывается и, наконец, viewportBottomObserverCallback вызывается. Это всегда так? Этот вопрос важен, потому что если я знаю, что эти события DOM всегда вызываются в этой последовательности, то мой код станет очень детерминированным. Обычно это не относится к каким-либо другим событиям DOM.

Чтобы лучше это представить, я прилагаю скриншот профилировщика моего Chrome. Часть внутри синего цвета — это мой обратный вызов наблюдателя пересечения.

введите описание изображения здесь

Редактировать:

Я тестирую это в Chrome в адаптивном режиме с устройством iPhone 6/7/8.

Еще один вопрос: происходит ли вычисление и постановка в очередь задач (intersection observer) в цикл событий только после update layer tree завершения, в частности, этой задачи — https://w3c.github.io/IntersectionObserver/#calculate-intersection-rect-algo ?

Ответ №1:

Подводя итог —

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

Так что да! Она детерминирована.

Отступая назад, браузер использует цикл событий для переключения между сценариями, рендерингом, рисованием, подключением к сети, организацией событий. Во время каждого поворота цикла событий выполняется одна макрозадача. Макрозадачи — это такие действия, как события пользовательского интерфейса (mousemove), манипулирование DOM и setTimeout. Микрозадачи выполняются после удаления макрозадачи из очереди. Таким образом, такие вещи, как IntersectionObserver и Promise.resolve, выполняются в очереди микрозадач перед рендерингом и рисованием.

https://www.w3.org/TR/intersection-observer/#event-loop

https://javascript.info/event-loop