requestAnimationFrame API - Анимация во время интенсивной JavaScript функции - PullRequest
1 голос
/ 17 июня 2020

У меня есть долгая функция блокировки потоков в веб-приложении. Во время его выполнения хотелось бы показать иконку анимации. Я хочу использовать Window. requestAnimationFrame () . Источники, с которыми я работал:


Я понимаю, что мне нужна функция - я называю ее animateLoadingIcon () -, чтобы обновить мой рисунок. В теле функции я должен, наконец, вызвать requestAnimationFrame (animateLoadingIcon) , чтобы начать рекурсивное обновление представления.

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

function animateLoadingIcon() {
rotateCount = (new Date().getTime() - starttime) / 3;
if (rotateCount > 359) {
  rotateCount %= 360;
}
divLoadingIcon.style.transform = 'rotate(' + rotateCount + 'deg)';
requestedAnimationFrame = requestAnimationFrame(animateLoadingIcon);

}

Функция, которую я изначально хочу выполнить, называется cal c (), где вызывается animateLoadingIcon ().

function calc() {

let randomMills = Math.random()*6000;
console.log("Start with duration: " + randomMills +"ms.")

starttime = new Date().getTime();
let recentTime = new Date().getTime();

let i = 0;

animateLoadingIcon();   
while (recentTime < starttime+randomMills) {
    i++;
    isPrime(i);
    recentTime = new Date().getTime();

} 
cancelAnimationFrame(requestedAnimationFrame);    

}

Я ожидаю, что колесо повернется, когда я нажимаю на кнопку, и остановится, когда останется while-l oop. Однако это не так. Может кто-нибудь указать на мои ошибки?

Ниже приведен пример jsfiddle https://jsfiddle.net/71vqarLs/8/

Ответы [ 2 ]

1 голос
/ 18 июня 2020

Спасибо за полезный вклад. Подсказки по передаче блокирующего потока while-l oop на аутсорсинг работнику были актуальны.

Я в основном сейчас вызываю только

function calc() {

    animateLoadingIcon();   
    worker.postMessage([randomMills, starttime])

}

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

worker.onmessage = function (e) {
    cancelAnimationFrame(requestedAnimationFrame);
}

Это помещает код блокировки в отдельный поток, в то время как requestAnimationFrame может спокойно работать в основном потоке.

1 голос
/ 17 июня 2020

WebWorkers было бы лучшим решением для этого, и это был бы «правильный» способ сделать это.

Использование Promise и async / await , используя a setTimeout l oop вместо while l oop, так что каждый вызов isPrime и каждая итерация l oop откладываются в событии l oop и позволяют анимации выполняться между ними.

jsfiddle demo: https://jsfiddle.net/cxews089/

  await new Promise(res => {
    var loop = () => {
      var tid = setTimeout(() => {
        if (recentTime < starttime + randomMills) {
          i++;
          isPrime(i);
          recentTime = new Date().getTime();
          loop()
        } else {clearTimeout(tid);res();}
      }, 0)
    };
    loop()
  });

Не слишком красиво и определенно можно написать более элегантно, но это работает. Вероятно, asyn c функция l oop также будет работать как однострочный эквивалент.
Конечно, будут накладные расходы, и вы можете захотеть выполнить разбиение вызовов на isPrime или что-то еще, что вы вызываете.

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