#javascript #canvas #settimeout
#javascript #холст #settimeout
Вопрос:
У меня есть скрипт, который рисует кучу строк на canvas, но это довольно интенсивно, поэтому во время рендеринга браузер зависает на несколько секунд. Я добавил setTimeout (), чтобы браузер не зависал, и это фактически испортило мой скрипт. Сложно объяснить как, поэтому у меня есть два примера онлайн:
Без setTimeout() :http://www.modwebsolutions.com/test1
С помощью setTimeout() :http://www.modwebsolutions.com/test2
Обратите внимание, что я меняю только одну строку во всем скрипте, то есть строку 69:
без setTimeout(): vLoop();
с помощью setTimeout(): setTimeout(vLoop,1);
Комментарии:
1. можете ли вы указать нам фактический код
vLoop
Ответ №1:
Проблема здесь, как намекали другие, заключается в том, что вы рисуете линии по квадранту за раз. Как только SetTimeout
метод вызывается и первый vLoop
возвращает результат, код переходит к следующему drawVertical
, который изменяет все глобальные переменные и так далее.
Что вам нужно сделать, так это синхронизировать то, как вы вызываете vLoop и как вы меняете глобальные переменные.
В принципе, это решение:
Заменить …
drawVertical(c,-1*step,-1*stepInt,-1*bigStep,xStart,xEnd,y/2 50,y);
drawVertical(c,step,stepInt,bigStep,xStart,xEnd,y/2 50,y);
drawVertical(c,-1*step,-1*stepInt,-1*bigStep,xStart,xEnd,y/2-50,0);
drawVertical(c,step,stepInt,bigStep,xStart,xEnd,y/2-50,0);
… с помощью …
var q = new Array();
q[0] = [c,-1*step,-1*stepInt,-1*bigStep,xStart,xEnd,y/2 50,y];
q[1] = [c,step,stepInt,bigStep,xStart,xEnd,y/2 50,y];
q[2] = [c,-1*step,-1*stepInt,-1*bigStep,xStart,xEnd,y/2-50,0];
q[3] = [c,step,stepInt,bigStep,xStart,xEnd,y/2-50,0];
drawQuadrant(q, 0);
Замените вашу drawVertical
функцию на …
function drawQuadrant(q, i)
{
var r = q[i];
c__ = r[0];
step__ = r[1];
stepInt__ = r[2];
bigStep__ = r[3];
xStart__ = r[4];
xEnd__ = r[5];
yStart__ = r[6];
yEnd__ = r[7];
vLoop(q,i);
}
измените vLoop
прототип функции, чтобы он выглядел следующим образом …
function vLoop(q,i)
и, наконец, замените свой рекурсивный vLoop
вызов (изнутри vLoop) на …
if ((xStart__ > 0) amp;amp; (xStart__ < window.innerWidth))
{
setTimeout( function(){vLoop(q,i)}, 1 );
}
else if ( i < 4)
{
setTimeout( function(){drawQuadrant(q,i)}, 1 );
}
В последнем блоке это гарантирует, что квадранты не переступают друг через друга.
Ответ №2:
drawVertical(c,-1*step,-1*stepInt,-1*bigStep,xStart,xEnd,y/2 50,y);
drawVertical(c,step,stepInt,bigStep,xStart,xEnd,y/2 50,y);
drawVertical(c,-1*step,-1*stepInt,-1*bigStep,xStart,xEnd,y/2-50,0);
drawVertical(c,step,stepInt,bigStep,xStart,xEnd,y/2-50,0);
Вы вызываете сразу 4 рекурсивные функции vLoop
. Проблема здесь в том, что setTimeout
неблокируется там, где блокируется рекурсия as. Итак, в принципе, теперь у вас есть все 4 из этих обратных функций, работающих параллельно, а не последовательно.
Другая проблема заключается в том, что все 4 ссылаются и путаются с глобальным состоянием, и вся ваша программа ломается.
Комментарии:
1. Они все еще однопоточные, поэтому сказать, что они выполняются параллельно, не совсем точно.
2. @NickCraver Выполнение с разделением по времени фактически выполняется параллельно. Чем использование setTimeout отличается от разделения по времени?
3. @Raynos — Вы никогда не будете внутри этого метода более одного раза одновременно, что является определением parallel 🙂
4. @NickCraver но вы будете находиться внутри набора функций, выполняемых рекурсивно более одного раза за раз. Отдельная функция не выполняется параллельно, но рекурсивное выполнение выполняется.
5. @Raynos — Это не’t…at ни одна строка кода, которую он запускает, не будет выполняться одновременно
Ответ №3:
Происходит то, что setTimeout()
задерживает все это выполнение на более поздний срок. К сожалению, к этому моменту все ваши глобальные переменные переместились на свои конечные позиции из начального цикла, поскольку он завершился до того, как была нарисована первая строка.
Если бы вы увеличили время ожидания (чтобы на используемые вами общие переменные не влияли до времени отрисовки), вы могли бы достичь желаемого, например:
setTimeout(function() {
drawVertical(c,-1*step,-1*stepInt,-1*bigStep,xStart,xEnd,y/2 50,y);
drawVertical(c,step,stepInt,bigStep,xStart,xEnd,y/2 50,y);
drawVertical(c,-1*step,-1*stepInt,-1*bigStep,xStart,xEnd,y/2-50,0);
drawVertical(c,step,stepInt,bigStep,xStart,xEnd,y/2-50,0);
});
Тогда это сработало бы (но это опасно, порядок не является абсолютно гарантированным!)
Комментарии:
1. Это просто откладывает весь процесс рисования на потом. Как только блок начинает выполняться, у вас по-прежнему возникает первоначальная проблема зависания браузера.
2. @Musaul — Это будет при обратном вызове по времени, но вы можете смягчить это, указав для продолжительности тайм-аута значение, отличное от 0, умножив его на
i
, например, чтобы разделить их на промежутки.