LINUX.ORG.RU

jQuery: запуск фоновых процессов


0

1

Есть простенькая задача для lazy-загрузки медленных частей страницы.

Суть такая. Всякие тормозные счётчики и прочее ставим в виде комментариев и потом, после загрузки и показа всей страницы, «раскомментируем» их. Например:

<span class="bors_lazy_load"><!--<center><a href="http://s02.flagcounter.com/more/NNik"><img src="http://s02.flagcounter.com/count/NNik/bg=FFFFFF/txt=000000/border=CCCCCC/columns=2/maxflags=12/viewers=0/labels=0/" alt="free counters" /></a></center>--></span>

$(function(){

    $('.bors_lazy_load').each(function(){
        el = $(this)
        html = ''+el.html()
        if(g = html.match(/^<!--([^\0]+)-->$/m))
            el.html(g[1])
    })
})

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

Первая мысль — запустить размаскировку асинхронно. В цикле не производить замену html, а запустить отложенный процесс, который это сделает. Например, через windows.setTimeout() с малым временем задержки.

Но в setTimeout нельзя передать параметр вызываемой функции. А нам нужно в параллельной задаче знать, что конкретно менять.

Есть мысли, как с этим бороться?

★★★★★

умвр @ chomium 14.0.835.35

<html>
<head>
<script src="http://code.jquery.com/jquery-latest.js"></script>
</head>
<body>
<div id="smth"></div>
<script type="text/javascript">
function do_smth(arg) {
    $('#smth').html(arg);
    setTimeout('do_smth('+(arg+1)+')', 1000);
}
setTimeout('do_smth(0)', 2000);
</script>
</body>
</html>
anonymous ()
Ответ на: умвр @ chomium 14.0.835.35 от anonymous

>'do_smth(0)'

Во-первых, это сегодня крайне некошерно :) Считается позавчерашним днём и depricated.

Во-вторых, вопрос _что_ передавать. Единственное, что в голову приходит — индекс для массива $('.bors_lazy_load'). Но это совсем уродливо.

Нет ли более изящного решения?

KRoN73 ★★★★★ ()

А кто мешает попользовать замыкание?

$(function(){
    $('.bors_lazy_load').each(function(){
        var el = $(this)
        setTimeout(function(){
            var html = ''+el.html()
            if(var g = html.match(/^<!--([^\0]+)-->$/m))
                el.html(g[1])
        })
    })
})

Но на самом деле у предложенного подхода есть большой минус: любой тормозной кусок содержащий хоть один document.write поломает страницу

anonymous ()
Ответ на: комментарий от anonymous

>любой тормозной кусок содержащий хоть один document.write поломает страницу

У jQuery .html(something) не выполняет скриптов в записываемом. Так что — пофиг, это идея только для статики.

setTimeout(function(){
var html = "+el.html()

Э... el же будет читаться в момент срабатывания функции и будет неопределённым значением. Или я не прав?

KRoN73 ★★★★★ ()
Ответ на: комментарий от KRoN73

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

<?php
// counter.php
$rnd = rand(2, 5);
sleep($rnd);
header('Content-Type: image/png');
$im = @imagecreate(80, 50)
    or die('Cannot Initialize new GD image stream');
$background_color = imagecolorallocate($im, 200, 200, 200);
$text_color = imagecolorallocate($im, 40, 40, 40);
@$text = ($_GET['c']?$_GET['c']:'*') . '; ' . $rnd;
imagestring($im, 5, 20, 20,  $text, $text_color);
imagepng($im);
imagedestroy($im);
?>

<!-- index.html -->
<html>
<head>
<script src="http://code.jquery.com/jquery-latest.js"></script>
</head>
<body>
<div id="smth"></div>
<span class="bors_lazy_load" id="lazy_bors-01"><!--<img src="counter.php?c=1" />--></span>
<span class="bors_lazy_load" id="lazy_bors-02"><!--<img src="counter.php?c=2" />--></span>
<span class="bors_lazy_load" id="lazy_bors-03"><!--<img src="counter.php?c=3" />--></span>
<span class="bors_lazy_load" id="lazy_bors-04"><!--<img src="counter.php?c=4" />--></span>
<script type="text/javascript">
function async_uncomment(id) {
    el = $('#'+id);
    html = ''+el.html();
    if (g = html.match(/^<!--([^\0]+)-->$/m)) {
        el.html(g[1]);
    }
}
$(document).ready(function() {
    $('#smth').html('started');
    /*$('.bors_lazy_load').each(function() {
        el = $(this);
        html = ''+el.html();
        if (g = html.match(/^<!--([^\0]+)-->$/m)) {
            el.html(g[1]);
        }
    });*/
    $('span[id|="lazy_bors"]').each(function() {
        el = $(this);
        setTimeout('async_uncomment(\''+(el.attr('id'))+'\')');
    });
    $('#smth').html('finished');
});
</script>
</body>
</html>

anonymous ()
Ответ на: комментарий от KRoN73

Э... el же будет читаться в момент срабатывания функции и будет неопределённым значением. Или я не прав?


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

var el
то el становится локальной для контекста обработчика each. А за счет замыкания контекста setTimeout использует именно тот экземпляр, который порождается на каждой итерации.

anonymous ()

1. добавлять контент через appendchild 2. Не химичить с контентом, указав размеры и display:none, а жабаскриптом менять свойство css.

Vit ★★★★★ ()

у меня для вас несколько открытий:

1. jQuery позволяет задавать более одного jQuery(window).load();

2. Отдельные элементы страницы тоже могут иметь хук onload

3. через setTimeout можно передать параметры таким макаром:

a = 1;
setTimeout(function() {
    alert(a);
}, 500);

>Активация кода идёт синхронная
что, опять же, мешает засунуть «чувствительные» части в отдельные процессы с помощью того же setTimeout(function, 0) ?

AGUtilities ★★★ ()
Ответ на: комментарий от KRoN73

Взаимоисключающие параграфы детектед

> Во-первых, это сегодня крайне некошерно :) Считается позавчерашним днём и depricated.

Ты используешь <center> и рассуждаешь про некошерность и deprecatedness? О_о

Apple-ch ★★ ()
Ответ на: Взаимоисключающие параграфы детектед от Apple-ch

>Ты используешь <center> и рассуждаешь про некошерность и deprecatedness?

Это не мой код, сторонний и уже не первый год стоящий :) И поменять его можно в любой момент. Вопрос же не об этом…

KRoN73 ★★★★★ ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.