Почему мои setInterval и setTimeout Animations ведут себя неожиданно при переключении окон [duplicate]

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

Ваш лучший выбор - использовать динамический Sql.

Обратите внимание, что динамический sql очень часто представляет угрозу безопасности, и вы должны защищать свой код от атак sql injection .

Я бы, вероятно, сделал бы что-то вроде этого:

Declare @Sql nvarchar(500)
Declare numberOfColumns int;

select @numberOfColumns = count(1)
from information_schema.columns
where table_name = 'HR_EmployeeProvisions'
and column_name IN(@RateOfEmployee, @RateOfEmployer)

if @numberOfColumns = 2 begin

Select @Sql = 'SELECT EmployeeCode, '+ QUOTENAME(@RateOfEmployee) +' ,'+ QUOTENAME(@RateOfEmployer) +
'FROM HR_EmployeeProvisions'

exec(@Sql)
end

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

Примечание. : в вашем слое презентации вы должны обработать параметр, чтобы выбор не выполнялся, поскольку имена столбцов недействительны.

147
задан csguimaraes 30 April 2013 в 22:12
поделиться

9 ответов

В большинстве браузеров неактивные вкладки имеют невысокое выполнение, и это может повлиять на таймеры JavaScript.

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

Вот пример ванильного JavaScript анимированный переход с использованием requestAnimationFrame:

var target = document.querySelector('div#target')
var startedAt, duration = 3000
var domain = [-100, window.innerWidth]
var range = domain[1] - domain[0]

function start() {
  startedAt = Date.now()
  updateTarget(0)
  requestAnimationFrame(update)
}

function update() {
  let elapsedTime = Date.now() - startedAt

  // playback is a value between 0 and 1
  // being 0 the start of the animation and 1 its end
  let playback = elapsedTime / duration

  updateTarget(playback)
  
  if (playback > 0 && playback < 1) {
  	// Queue the next frame
  	requestAnimationFrame(update)
  } else {
  	// Wait for a while and restart the animation
  	setTimeout(start, duration/10)
  }
}

function updateTarget(playback) {
  // Uncomment the line below to reverse the animation
  // playback = 1 - playback

  // Update the target properties based on the playback position
  let position = domain[0] + (playback * range)
  target.style.left = position + 'px'
  target.style.top = position + 'px'
  target.style.transform = 'scale(' + playback * 3 + ')'
}

start()
body {
  overflow: hidden;
}

div {
    position: absolute;
    white-space: nowrap;
}
<div id="target">...HERE WE GO</div>


Для фоновых задач (не связанных с UI)

Комментарий @UpTheCreek:

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

Если у вас есть фоновые задачи, которые нуждается в для точного выполнения с заданными интервалами, вы можете использовать HTML5 Web Workers . Взгляните на ответ Möhre ниже для более подробной информации ...

CSS против JS «анимация»

Эта проблема и многие другие можно было избежать, используя CSS-переходы / анимации вместо анимации на основе JavaScript, что добавляет значительные накладные расходы. Я бы порекомендовал этот плагин jQuery , который позволит вам использовать переходы CSS так же, как методы animate().

128
ответ дан 24 revs, 2 users 99% 18 August 2018 в 02:13
поделиться
  • 1
    Я попробовал это на FireFox 5, и setInterva'l все еще работает, даже если вкладка не находится в фокусе. Мой код в 'setInterval' перемещает слайд-шоу с помощью 'animate ()'. Похоже, анимация поставлена ​​в очередь с помощью FireFox. Когда я вернусь на вкладку, FireFox сразу же выгружает очередь один за другим, что приводит к быстрому перемещению слайд-шоу, пока очередь не будет пустой. – nthpixel 27 August 2011 в 00:53
  • 2
    @nthpixel добавит .stop (как ответ на www) помощь в ситуации tat (так как каждый раз это будет очищать предыдущие анимации) – gordatron 26 September 2011 в 11:58
  • 3
    @gordatron - .stop не помогает моей ситуации. Такое же поведение. И я сейчас на FireFox 6.0.2. Интересно, так ли jQuery реализует .animate. – nthpixel 29 September 2011 в 20:08
  • 4
    @cvsguimaraes - да хорошая точка. Знаете ли вы что-нибудь в спецификации, которая гарантирует, что веб-работники будут работать, даже если на вкладке фона? Я немного обеспокоен тем, что поставщики браузеров будут произвольно решать зажать их в будущем тоже ... – UpTheCreek 3 March 2013 в 21:45
  • 5
    Я бы изменил следующую строку кода, чтобы прочитать before = now;, чтобы получить прошедшее время с start вместо end предыдущего вызова. Обычно это то, что вы хотите, когда оживляете вещи. Как и сейчас, если выполнение функции интервала занимает 15 мс, elapsedTime даст 35 мс (вместо 50 мс, который является интервалом) при следующем вызове (когда вкладка активна). – Jonas Berlin 24 July 2015 в 11:52

Я думаю, что лучшее понимание этой проблемы в этом примере: http://jsfiddle.net/TAHDb/

Я делаю здесь простую вещь:

Имейте интервал в 1 секунду и каждый раз скройте первый интервал и переместите его на последний, и покажите 2-й интервал.

Если вы остаетесь на странице, он работает так, как предполагается. Но если вы скроете вкладку в течение нескольких секунд, когда вы вернетесь, вы увидите проветрившую вещь.

. Как и все события, которые не были укусом в то время, когда вы были неактивны, все будет в одно время , поэтому в течение нескольких секунд вы получите как X-события. они настолько быстры, что можно увидеть все 6 пролетов сразу.

Таким образом, швы хром только задерживают события, поэтому, когда вы возвращаетесь, все события будут происходить, но все сразу ...

. Правое приложение было для этого простым просмотром слайдов. Представьте, что числа являются изображениями, и если пользователь останется с скрытой вкладкой, когда он вернется, он увидит, что все imgs плавающие, Полностью mesed.

Чтобы исправить это, используйте stop (true, true), например pimvdb. Это очистит очередь событий.

5
ответ дан 1st4ck 18 August 2018 в 02:13
поделиться
  • 1
    На самом деле это из-за requestAnimationFrame, который использовался jQuery. Из-за некоторых причуд, которые он имел (как этот), они удалили его. В 1.7 вы не видите этого поведения. jsfiddle.net/TAHDb/1 . Поскольку интервал один раз в секунду, это фактически не влияет на проблему, которую я опубликовал, так как максимум для неактивных вкладок также один раз в секунду - так что это не имеет никакого значения. – pimvdb 7 November 2011 в 19:38

Существует решение использовать веб-работников (как упоминалось ранее), потому что они запускаются в отдельном процессе и не замедляются

. Я написал крошечный скрипт, который можно использовать без изменений в вашем код - он просто переопределяет функции setTimeout, clearTimeout, setInterval, clearInterval.

Просто включите его перед всем своим кодом.

подробнее здесь

29
ответ дан jdmdevdotnet 18 August 2018 в 02:13
поделиться
  • 1
    Я тестировал его на проекте, включая библиотеки, которые использовали таймеры (поэтому я не мог сам реализовать своих работников). Оно работало завораживающе. Спасибо за эту библиотеку – ArnaudR 7 October 2015 в 12:30
  • 2
    Мой мозг взорвался, когда я тестировал некоторый код setInterval .... затем, наконец, открыл это ... СПАСИБО ВАС СПАСИБО – Clay 15 October 2015 в 11:30
  • 3
    Спасибо, что поделились этим, очень полезно! – yodalr 11 April 2017 в 16:58
  • 4
    @ ruslan-tushov просто попробовал его на chrome 60, но, похоже, он не имеет никакого эффекта ... Я вызываю несколько функций из нескольких setTimeout, чтобы добавлять / удалять элементы в DOM, которые анимируются css-анимациями, и я вижу, что они зависают с некоторой задержкой после переключения табуляции (как обычно, без плагинов) – neoDev 21 August 2017 в 01:26
  • 5
    @neoDev Вы загружаете HackTimer.js (или HackTimer.min.js) перед любым другим JavaScript? – Davide Patti 7 September 2017 в 14:15

Воспроизведение аудиофайла обеспечивает полное фоновое Javascript-производительность на данный момент

. Для меня это было самое простое и наименее навязчивое решение - помимо воспроизведения слабого / почти пустого звука нет других потенциальные побочные эффекты

Здесь вы можете найти подробности: https://stackoverflow.com/a/51191818/914546

(Из других ответов I что некоторые люди используют разные свойства тега Audio, я действительно задаюсь вопросом, можно ли использовать тег Audio для полной производительности, фактически ничего не играя)

0
ответ дан Kaan Soral 18 August 2018 в 02:13
поделиться

Я столкнулся с той же проблемой со звуковым затуханием и проигрывателем HTML5. Он застрял, когда вкладка стала неактивной. Поэтому я узнал, что WebWorker разрешено использовать интервалы / таймауты без ограничений. Я использую его для публикации «тиков» на главный javascript.

Код WebWorkers:

var fading = false;
var interval;
self.addEventListener('message', function(e){
    switch (e.data) {
        case 'start':
            if (!fading){
                fading = true;
                interval = setInterval(function(){
                    self.postMessage('tick');
                }, 50);
            }
            break;
        case 'stop':
            clearInterval(interval);
            fading = false;
            break;
    };
}, false);

Основной Javascript:

var player = new Audio();
player.fader = new Worker('js/fader.js');
player.faderPosition = 0.0;
player.faderTargetVolume = 1.0;
player.faderCallback = function(){};
player.fadeTo = function(volume, func){
    console.log('fadeTo called');
    if (func) this.faderCallback = func;
    this.faderTargetVolume = volume;
    this.fader.postMessage('start');
}
player.fader.addEventListener('message', function(e){
    console.log('fader tick');
    if (player.faderTargetVolume > player.volume){
        player.faderPosition -= 0.02;
    } else {
        player.faderPosition += 0.02;
    }
    var newVolume = Math.pow(player.faderPosition - 1, 2);
    if (newVolume > 0.999){
        player.volume = newVolume = 1.0;
        player.fader.postMessage('stop');
        player.faderCallback();
    } else if (newVolume < 0.001) {
        player.volume = newVolume = 0.0;
        player.fader.postMessage('stop');
        player.faderCallback();
    } else {
        player.volume = newVolume;
    }
});
60
ответ дан Möhre 18 August 2018 в 02:13
поделиться
  • 1
    Ухоженная! Теперь давайте надеяться, что они не будут «исправлены». это. – pimvdb 27 September 2012 в 07:25
  • 2
    Большой! Этот подход следует использовать, когда вам нужны таймеры для работы, но не только для исправления некоторых проблем с анимацией! – Konstantin Smolyanin 18 April 2013 в 12:23
  • 3
    Я сделал большой метроном с этим. Интересно, что все наиболее популярные html5-драм-машины не используют этот метод и вместо этого используют нижний регулярный setTimeout. skyl.github.io/grimoire/fretboard-prototype.html - хром или сафари играют его лучше всего, прямо сейчас. – Skylar Saveland 28 December 2013 в 07:52

Сильно под влиянием библиотеки Руслана Тушова я создал свою небольшую библиотеку . Просто добавьте скрипт в <head>, и он исправит setInterval и setTimeout с теми, которые используют WebWorker.

1
ответ дан Marii 18 August 2018 в 02:13
поделиться
  • 1
    просто попробовал его на chrome 60, но он, похоже, не имеет никакого эффекта ... Я вызываю несколько функций из нескольких setTimeout, чтобы добавлять / удалять элементы в DOM, которые анимируются анимацией css, и я вижу, что они зависают с некоторой задержкой после (как обычно, без плагинов) – neoDev 21 August 2017 в 01:16
  • 2
    Я использую его с Chrome 60. Можете ли вы сделать демо-версию и опубликовать ее по вопросам github? – Marii 21 August 2017 в 06:40

Просто выполните это:

var $div = $('div');
var a = 0;

setInterval(function() {
    a++;
    $div.stop(true,true).css("left", a);
}, 1000 / 30);

Неактивные вкладки браузера задерживают некоторые из функций setInterval или setTimeout.

stop(true,true) останавливает все буферизованные события и выполняет мгновенно только последняя анимация.

Теперь метод window.setTimeout() зажимает для отправки не более одного тайм-аута в секунду на неактивных вкладках. Кроме того, теперь он захватывает вложенные таймауты до наименьшего значения, разрешенного спецификацией HTML5: 4 мс (вместо 10 мс, которые он использовал для фиксации).

13
ответ дан pimvdb 18 August 2018 в 02:13
поделиться
  • 1
    Это полезно знать - например, для обновлений ajax, где последние данные всегда правильные, но для опубликованного вопроса это не означает, что анимация была значительно замедлена / приостановлена ​​как «a», не увеличивалось бы соответствующее количество раз? – gordatron 26 September 2011 в 11:56

Вот мое грубое решение

(function(){
var index = 1;
var intervals = {},
    timeouts = {};

function postMessageHandler(e) {
    window.postMessage('', "*");

    var now = new Date().getTime();

    sysFunc._each.call(timeouts, function(ind, obj) {
        var targetTime = obj[1];

        if (now >= targetTime) {
            obj[0]();
            delete timeouts[ind];
        }
    });
    sysFunc._each.call(intervals, function(ind, obj) {
        var startTime = obj[1];
        var func = obj[0];
        var ms = obj[2];

        if (now >= startTime + ms) {
            func();
            obj[1] = new Date().getTime();
        }
    });
}
window.addEventListener("message", postMessageHandler, true);
window.postMessage('', "*");

function _setTimeout(func, ms) {
    timeouts[index] = [func, new Date().getTime() + ms];
    return index++;
}

function _setInterval(func, ms) {
    intervals[index] = [func, new Date().getTime(), ms];
    return index++;
}

function _clearInterval(ind) {
    if (intervals[ind]) {
        delete intervals[ind]
    }
}
function _clearTimeout(ind) {
    if (timeouts[ind]) {
        delete timeouts[ind]
    }
}

var intervalIndex = _setInterval(function() {
    console.log('every 100ms');
}, 100);
_setTimeout(function() {
    console.log('run after 200ms');
}, 200);
_setTimeout(function() {
    console.log('closing the one that\'s 100ms');
    _clearInterval(intervalIndex)
}, 2000);

window._setTimeout = _setTimeout;
window._setInterval = _setInterval;
window._clearTimeout = _clearTimeout;
window._clearInterval = _clearInterval;
})();
0
ответ дан Tengiz 18 August 2018 в 02:13
поделиться
  • 1
    Не могли бы вы объяснить, как работает ваше решение? – Eborbob 6 May 2016 в 08:49
  • 2
    postMessageHandler вызывает свое собственное событие, которое обрабатывает, тем самым имея бесконечный цикл, который не блокирует пользовательский интерфейс. И хотя он бесконечно цикличен, он проверяет каждую обработку событий, если есть функция тайм-аута или интервала для запуска. – foobored 7 May 2018 в 20:34

Мне удалось вызвать функцию обратного вызова минимум 250 мс с помощью аудио-тега и обработать его событие ontimeupdate. Его вызывали 3-4 раза в секунду. Его лучше, чем одна секунда с задержкой setTimeout

-2
ответ дан user7356139 18 August 2018 в 02:13
поделиться
Другие вопросы по тегам:

Похожие вопросы: