Javascript: как сделать простую задержку между выполнением кода javascript?

У меня есть цикл for, который повторяется более 10 000 раз в коде javascript. Цикл for создает и добавляет теги ‹div> в поле в DOM текущей страницы.

for(i = 0; i < data.length; i++)
{
    tmpContainer += '<div> '+data[i]+' </div>';
    if(i % 50 == 0) { /* some delay function */ }
}
containerObj.innerHTML = tmpContainer;

я хочу поставить задержку после каждых 50 тегов ‹div>, так что будет код на месте

/* some delay function */

потому что загрузка всех 10 000 тегов ‹div> занимает слишком много времени. Я хочу обновить поле кусками по 50 тегов ‹div>.

заранее спасибо.


person Vinay Jeurkar    schedule 06.02.2011    source источник


Ответы (5)


В таких ситуациях есть удобный трюк: используйте setTimeout с 0 миллисекундами. Это приведет к тому, что ваш JavaScript уступит место браузеру (чтобы он мог выполнять рендеринг, отвечать на ввод пользователя и т. Д.), Но не заставляя его ждать определенное время:

for (i=0;i<data.length;i++) {
    tmpContainer += '<div> '+data[i]+' </div>';
    if (i % 50 == 0 || i == data.length - 1) {
        (function (html) { // Create closure to preserve value of tmpContainer
            setTimeout(function () {
                // Add to document using html, rather than tmpContainer

            }, 0); // 0 milliseconds
        })(tmpContainer);

        tmpContainer = ""; // "flush" the buffer
    }
}

Примечание: T.J. Краудер правильно упоминает ниже, что приведенный выше код будет создавать ненужные функции на каждой итерации цикла (одна для установки закрытия, а другая в качестве аргумента для setTimeout). Вряд ли это будет проблемой, но при желании вы можете проверить его альтернативу, которая создает только функцию закрытия. однажды.

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

person David Tang    schedule 06.02.2011
comment
Это будет работать, но два комментария: 1. Он без необходимости создает новую функцию каждый раз, когда вы достигаете 50 div. Это 199 ненужных функций. Наверное, нормально, но все же этого можно избежать. 2. Более эффективно создать HTML в виде массива строк, а затем использовать a.join("") для создания одной большой строки, когда вы закончите, чем использовать конкатенацию строк для создания HTML. - person T.J. Crowder; 06.02.2011
comment
@ T.J. вы правы насчет обоих этих пунктов, но я не стал беспокоиться ради простоты: 1. Создание функции редко является проблемой производительности, особенно когда вашим узким местом является модель DOM, 2. Конкатенация строк - проблема только в IE, и часто быстрее в других браузерах, но даже для IE, поскольку я сбрасываю tmpContainer на пустую строку, строки никогда не становятся большими;) - person David Tang; 06.02.2011
comment
@ Box9: Только что видел: document.write?!?! Это категорически не сработает. appendChild и т. Д. В порядке. - person T.J. Crowder; 06.02.2011
comment
@ T.J. ну, он будет работать, но он просто перезапишет страницу, которая у вас была, так что это, вероятно, не будет работать как ожидалось;) Я надеюсь, что было ясно, что это просто указывает использование переменной html, а не tmpContainer. - person David Tang; 06.02.2011
comment
@ Box9: Интересная интерпретация произведения. ;-) Я бы удалил это как полностью вводящее в заблуждение и просто добавил бы комментарий html здесь для создания элементов. Кстати, раньше я ошибался, это ~ 398 совершенно ненужных функций (вы воссоздаете то, что создает замыкания, в которых даже меньше необходимости, чем в других). Кроме того, если не произойдет data.length % 50 == 0, это либо не приведет к выводу последних 1-49, либо, по крайней мере, для этого потребуется дублированный код. Вместо этого: pastie.org/1533736 Это все, чтобы дать хороший ответ , не доставляя вам хлопот. - person T.J. Crowder; 06.02.2011
comment
@ T.J. Я добавил ваши предложения к своему ответу. Я все еще не согласен с тем, насколько важны дополнительные функции, но я все равно связался с вашим кодом. Времени нет, спасибо за вклад. - person David Tang; 07.02.2011
comment
@ Box9: Приятно общаться с кем-то, кто не безумно обидчив. :-) Лучший, - person T.J. Crowder; 07.02.2011
comment
Вывод имеет значение, поэтому проблема решена со всеми вашими представлениями. Спасибо за это... - person Vinay Jeurkar; 07.02.2011
comment
эй, у меня тоже есть другой ... не могли бы вы тоже помочь с этим? stackoverflow.com/questions/4917790/ - person Vinay Jeurkar; 07.02.2011

Вы можете использовать функцию window.setTimeout, чтобы отложить выполнение некоторого кода:

if(i % 50 == 0) {
    window.setTimeout(function() {
        // this will execute 1 second later
    }, 1000);
}

Но ваш javascript продолжит выполнение. Это не остановится.

person Darin Dimitrov    schedule 06.02.2011

Я бы разбил код, создающий divs, в функцию, а затем запланировал бы выполнение этой функции периодически через setTimeout, например:

function createThousands(data) {
    var index;

    index = 0;
    doAChunk();

    function doAChunk() {
        var counter;

        for (counter = 50; counter > 0; --counter) {
            // Are we done?
            if (index >= data.length) {
                // Yup
                return;
            }

            // ...create a div...

            // Move to the next
            ++index;
        }

        // Schedule the next pass
        setTimeout(doAChunk, 0); // 0 = defer to the browser but come back ASAP
    }
}

Для выполнения работы используется одно закрытие doAChunk. Это закрытие имеет право на сборку мусора после завершения своей работы. (Подробнее: Замыкания не сложны < / а>)

Живой пример

person T.J. Crowder    schedule 06.02.2011
comment
@fehergeri: Моя проблема? Хм? - person T.J. Crowder; 06.02.2011
comment
@fehergeri: Понятно, вы имели в виду его проблему. Я имел дело с проблемой не делать промежуточных обновлений; оплавление - это совсем другое. - person T.J. Crowder; 06.02.2011

на это уходит много времени из-за переплавки. вы должны создать фрагмент документа, а затем добавить brats.

Когда происходит перекомпоновка в среде DOM?

Производительность Javascript - Dom Reflow - статья Google

сон не решит вашу проблему

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

процесс innerhtml нельзя приостановить или прервать.

вам нужно сгенерировать элементы один за другим, а после добавления 50 элементов создать задержку settimeout.

var frag = document.createDocumentFragment();

function addelements() {

   var e;
   for(i=0;i<50;++i) {
       e = document.createElement('div');
       frag.appendChild(e);
   }
   dest.appendChild(frag);
   window.setTimeout(addelements,1000);

}
person Gergely Fehérvári    schedule 06.02.2011

Вот настоящий трюк, чтобы поставить задержку в javascript без зависания браузера. Вам нужно использовать функцию ajax с синхронным методом, который будет вызывать php-страницу, и на этой php-странице вы можете использовать php-функцию sleep ()! http://www.hklabs.org/articles/put-delay-in-javascript

person Kaushik    schedule 05.10.2013
comment
Обратите внимание, что ответы только по ссылкам не приветствуются, ответы SO должны быть конечной точкой поиска. для решения (по сравнению с очередной остановкой ссылок, которые со временем устаревают). Пожалуйста, подумайте о добавлении здесь отдельного синопсиса, сохранив ссылку в качестве справочной. - person kleopatra; 05.10.2013