如何限制或减缓函数调用的数量(以提高性能)在这个函数调用中?

4
我有一个函数,长这样:

function someFunction(text) {
    $('.class').each(function() {
        var $this = $(this);
        if ($this.text().match(text)) {
           $this.addClass('found');
        } else {
           $this.removeClass('found');
        }
    });
}

该功能在键盘弹起事件中执行。

$('input[type=text]').keyup(function() {
   someFunction($(this).val());
});

如果在IE浏览器中存在大量.class元素,则可能会变慢。我认为,如果在每个函数完成之前再次执行该函数,则可以通过停止执行each调用来加快速度。我应该如何做到这一点?


2
这种情况不会发生。因为在执行 someFunction 时,JS/浏览器是单线程的,没有新的事件处理程序会被调用。 - Arun P Johny
:contains - Tushar
1
你可以尝试一些防抖动的方法。 - Arun P Johny
3个回答

8
您可以通过在keyup处理程序中添加轻微延迟来加快此过程,以便仅在输入结束后而不是在每次按键时影响DOM。您还可以使用:contains选择器查找元素。请尝试以下操作:
function someFunction(text) {
    $('.class').removeClass('found').filter(':contains("' + text + '")').addClass('found');
}

var timer;
$('input[type=text]').keyup(function() {
    clearTimeout(timer);
    timer = setTimeout(function() {
        someFunction(this.value);
    }, 100);
});

另外,正如@A.Wolff提到的那样,您可以缓存.class选择器,但前提是您在搜索时没有将任何.class元素动态添加到DOM中:

var $elements = $('.class');
function someFunction(text) {
    $elements.removeClass('found').filter(':contains("' + text + '")').addClass('found');
}

var timer;
$('input[type=text]').keyup(function() {
    clearTimeout(timer);
    timer = setTimeout(function() {
        someFunction(this.value);
    }, 100);
});

使用100毫秒延迟的setTimeout正是我已经做过的,但我认为可能有更好的方法。 - jcubic
2
可能 $('.class') 可以被缓存。 - A. Wolff
@jcubic,不幸的是,在这种情况下选择并不多。您受到正在处理的数据量的限制。 - Rory McCrossan

0
尝试在你的函数末尾添加return false;
function someFunction(text) {
    $('.class').each(function() {
        var $this = $(this);
        if ($this.text().match(text)) {
           $this.addClass('found');
        } else {
           $this.removeClass('found');
        }

    });
    return false;
}

2
这会在第一个元素后面打断,而不是在再次调用该函数时。 - jcubic
@jcubic,问题标题“在再次调用时中断jQuery each函数调用”表述不清楚您的目标是什么,因此我建议进行编辑。 - user3638471

0

由于我误解了问题,这里提供两个优化建议(两者可以一起使用):

缓存查询结果,并通过定时器偶尔更新

虽然不是很美观,但考虑到性能提升至关重要,这可能提供一个稳健的解决方案。

window.lastValue = null;

window.cachedElements = null;

window.updateCachedElements = function(){ cachedElements = $('.class'); };

function someFunction() {
    cachedElements.each(function() {
        var $this = $(this);
        if ($this.text().match(lastValue)) {
           $this.addClass('found');
        } else {
           $this.removeClass('found');
        }
    });
}

$('input[type=text]').keyup(function() {
    if(cachedElements === null) {
        updateCachedElements();
    }

    lastValue = $(this).val()

    someFunction();
});

setInterval(function(){ updateCachedElements(); someFunction(); }, 500);

使用防抖(一种节流的形式)将someFunction调用次数最小化为每100毫秒1次或每秒10次

someFunction定义之后(并在外部),执行以下操作:

someFunction = debounce(someFunction, 100);

underscore.js中实现的防抖功能:

_.debounce = function(func, wait, immediate) {
    var timeout, args, context, timestamp, result;

    var later = function() {
        var last = (Date.now || new Date().getTime()) - timestamp;

        if (last < wait && last >= 0) {
            timeout = setTimeout(later, wait - last);
        } else {
            timeout = null;
            if (!immediate) {
                result = func.apply(context, args);
                if (!timeout) context = args = null;
            }
        }
    };

    return function() {
        context = this;
        args = arguments;
        timestamp = _.now();
        var callNow = immediate && !timeout;
        if (!timeout) timeout = setTimeout(later, wait);
        if (callNow) {
            result = func.apply(context, args);
            context = args = null;
        }

        return result;
    };
};

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接