Когда и зачем использовать "тик" в Angular 2?

Я видел, что в классе компонентов Angular 2 используется следующее:

setTimeout(()=>{}, 0);

Это означает, что после 0 секунд вызывается пустая функция. Я знаю, что это связано с моделью событий Javascript, но не понимаю его полностью.

Пожалуйста, объясните, когда и почему это делается в Angular 2, используя небольшой пример реального мира с некоторым фрагментом кода.

Ответ 1

setTimeout(()=>{}, 0);

Заставляет Angular запускать обнаружение изменений для всего приложения, например ApplicationRef.tick

zone.js исправляет асинхронные API-интерфейсы (addEventHandler, setTimeout ,...) и запускает обнаружение изменений после завершения обратного вызова.

Ответ 2

Я добавлю ответ Гюнтера, так как он пока мал.

Он говорит:

setTimeout(()=>{}, 0); Заставляет Angular запускать обнаружение изменений для всего приложения

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

это можно сделать так:

const temp = window.setTimeout;
window.setTimeout = (...args) => {
    temp(...args)
    angular.triggerChangeDetection(); // or w.e they use
}

Таким образом, 0 означает, что обнаружение изменений происходит немедленно, а пустая функция - потому что мы не хотим ничего делать.

Ответ 3

Я помню, как задавал этот вопрос довольно давно. Ответ, который был в репозитории github под названием angular-flexslider, заключался в том, что он заменял $(document).ready(function() {...})) уровне компонентов.

Angular манипулирует DOM после загрузки страницы. Иногда можно увидеть обновление угловых выражений после загрузки страниц, когда процессор немного занят. Функция тайм-аута гарантирует, что код будет запущен ноль миллисекунд после того, как angular завершит обработку документа.

Мне никогда не приходилось это делать, и в наши дни с хуками жизненного цикла компонентов я не могу себе представить, что вам когда-нибудь понадобится снова (то есть, если вам действительно когда-либо это понадобилось). Но в англоязычных терминах эту причину я видел. Я также могу сказать, что я видел много кода Angular, написанного инженерами, в котором вы были бы очень уверены (насколько они знают Angular), и никогда не видел, чтобы кто-нибудь делал это.

Кроме того, это способ убедиться, что код, который вы хотите запустить, помещен в конец текущей очереди цикла событий. Это часто делается для производительности. Раньше я делал что-то вроде следующего для списков "бесконечной прокрутки" (теперь это все RxJS, Observables и т.д.). Рассмотрим этот код:

var res = []
function response ( d ) {
  var chunk = data.splice ( 0, 1000 );

  res = res.concat ( chunk.map ( ...do something ) );

  if ( data.length > 0 ) {
    setTimeout ( () => { response ( data ) }, 0 );
  }
}

Поскольку вы рекурсивно вызываете response через setTimeout для обработки чанков, даже если он имеет интервал 0, вы делаете это в пакетах, и каждый из этих пакетов будет обрабатываться в конце текущей очереди заданий (вместо простого создания стек событий в очереди событий, которые будут блокироваться).