Состояние гонки javascript

Я вызываю функцию javascript, которая устанавливает непрозрачность iframe неизвестное количество раз в быстрой последовательности. В основном это промежуточное звено от 0 до 100. вот код


   function setAlpha(value)
   {
       iframe.style.opacity = value * .01;
       iframe.style.filter = 'alpha(opacity =' + val + ')';
   }

Моя проблема в том, что впервые он работает в IE (7), а не в firefox (3.02). в Firefox я получаю задержку, а затем появляется документ содержимого с непрозрачностью 100. Если я вставлю в него предупреждение, он сработает, поэтому я предполагаю, что это состояние гонки (хотя я думал, что javascript был однопоточным) и что функция setAlpha вызывается до того, как завершится выполнение последней функции. Любая помощь будет принята с благодарностью. Я прочитал сообщение «Как избежать сообщения о состоянии гонки javascript», но я думаю, что это квалифицируется как нечто иное (плюс я не могу понять, как применить этот пример к этому).

Не могли бы вы предоставить дополнительную информацию о том, как вы вызываете эту функцию в цикле?

Rob 09.01.2009 05:12
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
1
2 501
4

Ответы 4

Javascript не работает с несколькими потоками, поэтому вы защищены от условий гонки (игнорируя предстоящую поддержку рабочих потоков в Safari и Firefox: D).

Простой вопрос, как вы вызываете setAlpha несколько раз, firefox, safari и opera, все они объединяют обновления таблиц стилей - например. они не будут перерисовывать или даже пересчитывать информацию о стилях во время работы js, если в этом нет необходимости. Таким образом, они будут рисовать только в том случае, если JS завершен.

Итак, если вы делаете

while(...) setAlpha(...)

они не будут обновляться, вам, вероятно, потребуется использовать setTimeout для запуска нескольких отдельных вызовов для обновления стиля.

Альтернативой может быть использование библиотеки, такой как jQuery, mootools и т. д., Которые, как я смутно помню, предоставляют упрощенный механизм для выполнения этих типов анимации и переходов. В качестве дополнительного бонуса я считаю, что по крайней мере несколько библиотек также будут использовать правила перехода webkit и анимации css, когда они доступны (например, Safari, и я считать последние сборки firefox)

[edit: caveat: я на самом деле не использовал ни одну из этих библиотек, я только читал о том, что они должны делать. Мои сайты отображаются в lynx так же, как и в любом другом браузере, потому что я не мог найти выход из бумажного пакета: D]

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

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

Уловка setTimeout(func, 0) обычно используется, чтобы заставить Javascript отложить выполнение func до тех пор, пока стек вызовов не станет пустым.

В коде:

function setAlpha(opacity){
   some_element.style.opacity = opacity;
}

/** 
* This WON'T work, because the browsers won't bother reflecting the 
* changes to the element's opacity until the call stack is empty, 
* which can't happen until fadeOut() returns (at the earliest)
**/
function fadeOut(){
    for (var i=0; i<10; i++){
        setAlpha(0.1*i);    
    }
}

/** 
* This works, because the call stack will be empty between calls
* to setAlpha()
**/
function fadeOut2(){
    var opacity = 1;
    setTimeout(function setAlphaStep(){
        setAlpha(opacity);
        if (opacity > 0){
            setTimeout(setAlphaStep, 10);        
        }
        opacity -= 0.1;  
    }, 0);
}

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

Обновлено: и вот хорошая статья о хитром стеке вызовов Javascript

Вы используете setTimeout или жесткий цикл? Если вы используете только цикл для вызова функции, переключитесь на использование setTimout.

пример:

   function setAlpha(value)
   {
       iframe.style.opacity = value * .01;
       iframe.style.filter = 'alpha(opacity =' + val + ')';
       if (value < 100 ) {
       setTimeout(function () {setAlpha(value+1)},20);
       }
   }
   setAlpha(0);

Как видите, это не просто однопоточный javascript. Это целый чертов браузер. Если ваш javascript зацикливается, вы зависаете во всем браузере. Таким образом, браузер приостанавливает работу, ожидая завершения работы javascript, и даже не имеет возможности обновить экран, в то время как ваш код быстро меняет некоторые значения dom.

Проблема в том, что большинство браузеров не перерисовывают, пока не будет пауза в выполнении javascript.

Это можно решить, используя setTimeout, как предлагали другие. Однако я рекомендую использовать что-то вроде jQuery или любую из библиотек javascript для создания анимации. Запуск setTimeout 100 раз - плохая идея, потому что длина анимации будет зависеть от браузера и скорости компьютера пользователя. Правильный способ создания анимации - указать, как долго она должна длиться, и проверить системное время, чтобы определить, как далеко должна продвинуться анимация.

function fadeIn(elem,animation_length) {
   var start = (new Date()).getTime();

   var step = function() {
      window.setTimeout(function() {
        var pct = ((new Date()).getTime() - start)/animation_length;
        elem.style.opacity = Math.min(pct,1);
        if (pct < 1) 
           step();
      },20);
   };
   step();
}

[edit:] Приведенный выше код предназначен только для иллюстрации того, как делать анимацию на основе системных часов, а не простых интервалов. Пожалуйста, используйте библиотеку для создания анимации. Приведенный выше код не будет работать в IE, потому что IE использует «filter: opacity (xx)» вместо «opacity». Об этом позаботятся библиотеки, а также предоставят такие полезные функции, как события завершения и возможность отмены анимации.

Другие вопросы по теме