【问题标题】:How to limit or throttle the number of function calls (in order to increase performance) in this function call?如何限制或限制此函数调用中的函数调用次数(以提高性能)?
【发布时间】:2018-04-07 09:40:28
【问题描述】:

我有一个看起来像这样的函数:

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

并且该函数在 keyup 事件中执行,

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

在 IE 上,如果有很多 .class 元素,它可能会很慢,我认为如果在每个函数完成之前再次执行函数,我可以停止执行每个调用,我可以加快速度。我该怎么做?

【问题讨论】:

标签: javascript jquery keyboard-events


【解决方案1】:

您可以通过向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正是我已经做过的,认为有更好的方法。
  • 是的,也许 $('.class') 可以被缓存
  • @jcubic 不幸的是,在这种情况下没有太多选择。您受到正在处理的数据权重的约束。
【解决方案2】:

尝试添加 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;
}

【讨论】:

  • 这将在第一个元素之后破坏每个元素,而不是在您再次调用该函数时。
  • @jcubic 问题标题“再次调用时中断 jQuery 的每个函数调用”对于您的目标的措辞真的不清楚,因此我建议进行编辑。
【解决方案3】:

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

缓存查询结果,只是偶尔定时更新

不是很漂亮,但考虑到性能提升至关重要,可能会提供一个强大的解决方案。

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);

使用 debounce(一种节流形式)将someFunction 调用次数降至 1/100 毫秒或每秒 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;
    };
};

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-02
    • 2023-03-03
    相关资源
    最近更新 更多