Состояние гонки индикатора занятости в Javascript

У меня есть следующий (javascript/jquery) код для отображения индикатора занятости (после задержки) во время загрузки изображения:

function imgUpdate(arg) {
    var loaded = false;

    $("#image").one("load", function(){
        loaded = true;
        $("#busyIndicator").hide();
    });

    setTimeout(function(){
        if (!loaded) {
            $("#busyIndicator").show();
        }
    }, 250);

    $("#image")[0].src = arg;
}

Иногда индикатор появляется и остается включенным. Как это возможно, если движок javascript браузера однопоточный? (Кстати, это в Firefox 3.)

Одно замечание: похоже, это происходит, когда загружаемое изображение уже кэшировано.

Еще одно замечание: если я захожу в свою консоль firebug, все строки в imgUpdate выполняются, но сообщение журнала внутри обработчика onload никогда не печатается при последующих вызовах imgUpdate.


person Jim Hunziker    schedule 21.05.2009    source источник
comment
так что в основном вы пытаетесь реализовать процесс загрузки с помощью jquery?   -  person TStamper    schedule 21.05.2009
comment
Да - тот, который не отображается, если изображение загружается быстро.   -  person Jim Hunziker    schedule 21.05.2009
comment
Нет условий гонки — JavaScript однопоточный. Ваша проблема в другом.   -  person Rex M    schedule 21.05.2009
comment
Можете ли вы воспроизвести проблему, если сразу отобразите индикатор в том же фрейме стека, не используя setTimeout()?   -  person Tamas Czinege    schedule 21.05.2009
comment
@DrJokepu: Да, в этом случае это все еще происходит. Кроме того, я добавил строку дополнительной информации в конец вопроса.   -  person Jim Hunziker    schedule 21.05.2009
comment
Имейте в виду, что стандарты HTML 4.01/XHTML 1.0/XHTML 1.1 не поддерживают событие onload для изображений. Если вы мне не верите, проверьте это: w3. org/TR/html401/struct/objects.html#h-13.2   -  person Tamas Czinege    schedule 21.05.2009


Ответы (4)


Есть ли какой-либо другой javascript на странице, который ломается? Если это так, это может быть не состояние гонки - JS может просто прекратить выполнение до того, как BusyIndicator снова будет скрыт...

person Matt Newby    schedule 21.05.2009
comment
Нет — firebug показывает, что ошибок нет и несвязанный запрос ajax все еще выполняется. - person Jim Hunziker; 21.05.2009

Мне трудно это повторить.

Вот реализация того, что вы делаете:

Версия с кэшированием: http://jsbin.com/uwuho.

Версия с запрещенным кешированием: (использует параметр, чтобы избежать кеширования) http://jsbin.com/oguvi

Нажмите F5/Ctrl-F5, чтобы увидеть, как это работает. (в частности, с версией, которая предотвращает кеширование)

С кэшированием или без него ни одна из версий не делает то, что вы описали.

Ваша проблема вероятно заключается в другом.

person cgp    schedule 21.05.2009
comment
Я тоже не смог воспроизвести это с помощью вашего кода. Но если бы проблема заключалась в чем-то другом, исправление, которое я разместил (в ответе здесь), похоже, не сработало бы. - person Jim Hunziker; 21.05.2009

Очистка тега src изображения, похоже, решает проблему:

function imgUpdate(arg) {
    var loaded = false;

    $("#image").one("load", function(){
        loaded = true;
        $("#busyIndicator").hide();
    });

    setTimeout(function(){
        if (!loaded) {
            $("#busyIndicator").show();
        }
    }, 250);

    $("#image")[0].src = "";
    $("#image")[0].src = arg;
}
person Jim Hunziker    schedule 21.05.2009

Возможно, вы захотите очистить тайм-аут в своем обратном вызове, чтобы он не срабатывал, если изображение загружено.

var timer = null;
function imgUpdate(arg) {
    var loaded = false;
    timer = setTimeout(function(){ 
        $("#busyIndicator").show();
        timer = null;
    }, 250);        
    $("#image").one("load", function(){
        if (timer) {
            clearTimeout(timer);
            timer = null;
        }
        $("#busyIndicator").hide();
    });
    $("#image")[0].src = arg;
}
person tvanfosson    schedule 21.05.2009
comment
Я пробовал это, но он все еще демонстрирует ту же проблему. Я обновил последнюю строку своего вопроса с некоторой дополнительной информацией. - person Jim Hunziker; 21.05.2009