jquery - JS/jQ 处理大量 setTimeouts 的更有效方法

标签 jquery settimeout

我正在开发一个网络艺术项目,该项目需要许多对象以一定的间隔淡入和淡出(我希望使用 100 个或更多对象)。我让 jQ 读取包含元数据的 XML 文件并将 Ps 附加到正文,然后根据元数据中的信息告诉其淡入和淡出。我正在使用 setTimeouts 来完成此任务。

这篇文章最终会占用大量资源。加载页面后一两分钟内,我的机器开始喘息。 (或者,我认为这可能不是资源问题,而是图形问题。)

有人可以提供一些建议来使其更加资源友好/高效吗?我感谢任何帮助!

这是实时链接:http://justwhatdoyoucallthis.com/trynottogiveup/ (小心资源占用)

这是相关的脚本:

$.ajax({
    type: 'get',
    url: 'problems.xml', /* ...which contains like 99 problems */
    dataType: 'xml',
    success: function(problems) {
        $(document).ready(function() {
            var winWidth=$(window).width();
            var winHeight=$(window).height();
            $(problems).find('problem').each(function() {
                var probType=$(this).attr('type');
                var probAppear=$(this).attr('appear');
                var probName=$(this).children('name').text();
                var probID=(probName.replace(/\s/g, '')).toLowerCase();
                var probIntensity=($(this).children('intensity').text()+5)*10;
                var probInterval=$(this).children('interval').text();
                var probDuration=$(this).children('duration').text();
                var ranLeft=Math.random()*winWidth-(probIntensity/2);
                var ranTop=Math.random()*winHeight-(probIntensity/2);
                $('body').append('<p id="'+probID+'" class="'+probType+'" style="left: '+ranLeft+'px; top: '+ranTop+'px; height: '+probIntensity+'px; width: '+probIntensity+'px;"><span>'+probName+'</span></p>');
                (function showLoop() {
                    if(probAppear=='fade') { var fadeInDuration=1000; } else { var fadeInDuration=0; }
                    $('#'+probID).delay(probInterval*1000).fadeIn(fadeInDuration).delay(probDuration*1000).fadeOut(1000);
                    setTimeout(showLoop, 1000);
                })();
            });
        });
    }
});

最佳答案

这是代码的优化版本,但就像 bvukelic 所说的那样,使用 Canvas 可能会更有效地实现整个概念。

我在代码中看到的问题是,延迟和淡入淡出操作确实是同步调用的,但超时是异步执行的,这意味着一段时间后,您在同一个对象上有多个操作流(这最多可达一百次)。

因此,解决方案是将重复超时作为回调附加到 .fadeOut() 操作。

$(function() {
    var $win = $(window),
        winWidth = $win.width(),
        winHeight = $win.height(),
        showLoop = function(prob) {
            var fadeInDuration = prob.appear == 'fade' ? 1000 : 0;
            $('#'+prob.id)
                .delay(prob.interval*1000)
                .fadeIn(fadeInDuration)
                .delay(prob.duration*1000)
                .fadeOut(1000, function() {
                    window.setTimeout(function() {
                        showLoop(prob); // synchronously repeated callback
                    }, 1000);
                });
        };

    $.ajax({
        type: 'get',
        url: 'problems.xml', /* ...which contains like 99 problems */
        dataType: 'xml',
        success: function(problems) {        
            $('problem', problems).each(function() {
                var $t = $(this),
                    probName = $('name', this).text(),
                    prob = {
                        type: $t.attr('type'),
                        appear: $t.attr('appear'),
                        name: probName,
                        id: probName.replace(/\s/g, '').toLowerCase(),
                        intensity: (parseInt($('intensity', this).text()) + 5) * 10,
                        interval: parseInt($('interval', this).text()),
                        duration: parseInt($('duration', this).text()),
                        pos: {
                            top = Math.random()*winHeight-(prob.intensity/2),
                            left = Math.random()*winWidth-(prob.intensity/2)
                        }
                    };

                $('<p>')
                    .append('<span>'+prob.name+'</span>')
                    .attr('id', prob.id)
                    .addClass(prob.type)
                    .width(prob.intensity)
                    .height(prob.intensity)
                    .css({
                        top: prob.pos.top,
                        left: prob.pos.left,
                    })
                    .appendTo('body');

                showLoop(prob);
            });
        }
    });
});

关于jquery - JS/jQ 处理大量 setTimeouts 的更有效方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14204667/

相关文章:

javascript - 自调用函数中递归函数的 setTimeout()

jquery - 带有单选按钮的 Bootstrap togglabe 选项卡的 html 表单

javascript - 具有多个输入的 jQuery 自动完成 - django-dynamic-formset

jquery - 当数据较少时阅读较少的文本 css 更改

javascript - 添加到 dom 的行未选择所有复选框列

javascript - XHR 请求的 setTimeout

javascript - 在 PhantomJS 中等待没有 setTimeout 的元素

javascript - 调用两个异步函数之一,但不能同时调用两个

javascript - 将数组作为函数参数传递给 setTimeout 与传递变量不同

javascript - 如何获取内容可编辑div的新文本?