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