Альтернатива jquery .each () не выполняется должным образом - PullRequest
0 голосов
/ 07 декабря 2010

Надеюсь, я что-то упустил, и это просто ...

У меня есть страница, которая просматривает список URL-адресов, делает Ajax-вызовы к ним (с помощью jquery), извлекает данные из возвращаемого HTML-кода и отображает их в таблице. Эти звонки работают нормально. Поскольку захват этих данных в режиме реального времени занимает некоторое время (возможно, до 5 минут для циклического перемещения по списку, возврата данных, его отображения и т. Д.), Такие браузеры, как Chrome и IE, «блокируются» во время такой тяжелой обработки - фактически Chrome периодически отображается сообщение «Page Unresponsive», в то время как IE, кажется, просто зависает, а затем неожиданно результаты отображаются на экране.

Чтобы решить эту проблему, я исследовал, как оптимизировать функцию jQuery .each (), и нашел собственный плагин с именем slowEach ( LINK ), который в основном вставляет небольшой тайм-аут после каждого цикла итерация - чтобы браузер получал ответ и не думал, что клиент не отвечает. Я обновил свой код, чтобы вызывать плагин slowEach вместо .each, и все работает отлично, ПОЧТИ! Кажется, что после первой итерации - плагин фактически выполняет дополнительный код - вплоть до конца моей функции обратного вызова, а затем внезапно хочет вернуться в цикл и правильно продолжить остальные итерации.

Мне трудно отследить, почему это происходит.

Вот мой код (parseXml - это просто функция обратного вызова, которая обрабатывает некоторые данные XML):

function parseXml(x)
{
  var $rowArray = $(x).find("[nodeName=z:row]");

   $rowArray.slowEach(250, function(index) {  
     // ... processing each returned row
    });
// ... extra processing after the loop is completed.  Show data on the screen.
};

Вот плагин slowEach:

$.slowEach = function( array, interval, callback ) {
        if( ! array.length ) return;
        var i = 0;
        next();
        function next() {
            if( callback.call( array[i], i, array[i] ) !== false )
                if( ++i < array.length )
                    setTimeout( next, interval );
        }
    };

    $.fn.slowEach = function( interval, callback ) {
        $.slowEach( this, interval, callback );
}; 

Этот код каким-то образом попадает в часть «дополнительной обработки» моего кода - только на первой итерации цикла. Очень странно. Может быть, некоторые дополнительные глазные яблоки могут помочь мне понять, почему код делает это. Дайте мне знать, если нужна дополнительная информация! Спасибо.

1 Ответ

1 голос
/ 07 декабря 2010

Когда .slowEach использует setTimout, это по существу откладывает выполнение этой функции (содержимое функции each) до тех пор, пока не будет выполнена вся остальная обработка страницы.Поэтому будет выполнен код вне вызовов slowEach, включая код после его вызова.Что вам нужно сделать, это добавить еще одну функцию к функции .sloweach, чтобы вызывать ее после обработки всех элементов, и поместить туда код // ... extra processing ....

Непроверенный код, но это должно сработать или, по крайней мере, заставить вас двигаться в правильном направлении:

function parseXml(x)
{
  var $rowArray = $(x).find("[nodeName=z:row]");

   $rowArray.slowEach(250, function(index) {  
        // ... processing each returned row
    }, function() {
        // ... extra processing after the loop is completed.  
        // Show data on the screen.
    });
};

Изменение плагина:

$.slowEach = function( array, interval, callback, onCompletion ) {
        if( ! array.length ) return;
        var i = 0;
        next();
        function next() {
            if( callback.call( array[i], i, array[i] ) !== false )
                if( ++i < array.length )
                    setTimeout( next, interval );
                else
                    setTimeout( onCompletion, interval );
        }
    };

    $.fn.slowEach = function( interval, callback, onCompletion  ) {
        $.slowEach( this, interval, callback, onCompletion  );
}; 
...