2016-04-21 2 views
1

Не уверен, что есть решение этой проблемы. Я хочу знать, есть ли способ обнаружить, когда браузер фактически обновляет интерфейс.Возможно ли обнаружить перерисовку/оплату в браузере?

Допустим, я хочу добавить класс к элементу непосредственно перед тем, как запустить запущенный синхронный блок кода после запуска синхронной функции, класс будет удален.

el.classList.add('waiting'); 
longRunningSynchronousTask(); 
el.classList.remove('waiting'); 

Если я запустил этот код, начнется работа по длительной работе и заблокирует пользовательский интерфейс перед добавлением класса. Я пробовал использовать MutationObserver и проверял элемент с помощью getComputedStyle, но это не работает, потому что они не отражают, когда обновление в реальном времени пользовательского интерфейса.

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

Единственное решение, которое работает вне работника, использует setTimeout. Мне бы хотелось узнать, столкнулся ли кто-нибудь с этой проблемой, и если есть какой-либо способ обнаружить перерисовку/перепланировку пользовательского интерфейса в браузере.

См. Мой пример для лучшей иллюстрации проблемы.

const el = document.querySelector('.target'); 
 
const isRed = c => c === 'red' || 'rgb(255, 0, 0)'; 
 

 
let classActuallyApplied = false; 
 

 
let requestId; 
 

 
const longRunningTask = (mil, onComplete) => { 
 
    if (classActuallyApplied) { 
 
    cancelAnimationFrame(requestId); 
 
    var start = new Date().getTime(); 
 
    while (new Date().getTime() < start + mil); 
 
    onComplete(); 
 
    } else { 
 
    requestId = requestAnimationFrame(longRunningTask.bind(null, mil, onComplete)); 
 
    } 
 
} 
 

 
const observer = new MutationObserver(function(mutations) { 
 
\t classActuallyApplied = mutations 
 
    \t .filter(mutation => { 
 
\t \t \t return mutation.type === 'attributes' && 
 
     \t mutation.attributeName === 'class' && 
 
     mutation.target.classList.contains('waiting'); 
 
\t \t }).length > 0; 
 
}); 
 

 
const observerConfig = { 
 
\t attributes: true, 
 
\t childList: false, 
 
\t characterData: false 
 
}; 
 

 
observer.observe(el, observerConfig); 
 

 
el.addEventListener('click', e => { 
 
\t el.classList.add('waiting'); 
 
    longRunningTask(1000 * 5,() => { 
 
    \t // el.classList.remove('waiting'); 
 
    }); 
 
});
.target { 
 
    height: 100px; 
 
    width: 100px; 
 
    background-color: gray; 
 
} 
 

 
.waiting { 
 
    background-color: red; 
 
}
<div class="target"> 
 
    target 
 
</div>

+0

Вы хотите его обнаружить или вызвать? Я не понимаю, какой смысл обнаружить в вашем случае. –

+0

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

+0

@ DenysSéguret Я хочу обнаружить, когда пользовательский интерфейс обновлен. Если я добавлю класс 'ожидания', например, он изменит цвет текста на красный. Я хочу знать, когда пользовательский интерфейс был обновлен для пользователя. Как только он будет обновлен, я могу начать свою долговременную задачу. –

ответ

0

Я считаю requestIdleCallback что вы ищете.

Таким же образом, что принятие requestAnimationFrame позволило нам планировать анимации правильно и максимально увеличить наши шансы на поражающие 60fps, requestIdleCallback будет планировать работу, когда есть свободное время в конце кадра, или когда пользователь неактивен.

К сожалению, это экспериментальная функция и поддерживается только в Chrome Canary.

Смежные вопросы