JavaScript 实现暴击事件

本文介绍了一种暴击任务生成器的设计与实现方法,通过设置特定条件如触发次数和时间间隔,可在短时间内达到预设次数时执行绑定的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在许多场景中,我们可能会遇到需要处理一种快速多次触发某事件,并处于某种阈值时,执行某一指定操作。例如,双击(即快速按鼠标左键两次)或更多击、连按键盘某键、某方法被执行数次等。其中,双击有对应的事件可以注册;然而,更多的情况是没有的类似事件方便我们注册使用的。那么,现在只能依靠我们勤劳的双手,来创造一个支持该功能的任务,并且该任务需要具有以下功能。

  • 可以在任务中绑定一个方法,以便在暴击后被调用。
  • 该任务可以被多次执行,包括也可以在已知事件中触发。
  • 只有当任务在短时间内执行到指定次数后,所注册的方法才会被调用。
  • 当短时间内执行了过多的次数,所注册的方法将不再被调用。
  • 短时间的界定方式是,通过指定一个连续两次任务执行间隔的最长时间,来进行控制。

那么,这该如何实现呢?

首先,我们需要定义一个函数,其接受一个用于设置选项的参数,该函数的作用是生成一个任务,该任务实际上应该也是一个函数,并接受一个可选的参数,用来传递额外的信息给绑定的方法,然后返回一个布尔值来指示当前的执行是否调用了绑定的方法。

function multipleHit(options) {
    // ToDo: Implement it.
    return null;
}

这个选项参数应当包含以下方法和属性。

  • process 方法,即该任务所绑定的方法。
    包含两个参数:第一个是整数型,表示第几次执行;第二个参数可选,任意类型,可用于接受在任务执行时,所传入的额外参数。
    该方法无返回值。
  • start 属性,可选,整数型,即短时间内第几次触发时调用任务中绑定的方法。
  • count 属性,可选,整数型,即绑定的方法在一轮快速触发时最多可被调用多少次。
  • timeout 属性,可选,整数型,即任意两次连续触发的最长时限,以微秒为单位。超出该时限后,几位另外一轮触发,计数器清零。
  • thisArg 属性,可选,任意型,即所绑定方法在被调用时的 this 参数。

很明显,当 start 为被设置或被设置为0,并且 count 属性未被设置时,所绑定的任务不会被执行次数限制。于是我们可以在 multipleHit 函数中进行以下改写。

if (!options.start && options.count == null) {
    return function (modelArg) {
        options.process.call(options.thisArg, 0, modelArg);
        return true;
    };
}

而除此以外,我们至少需要加上计时器和最近一次执行的时间记录了。

var count = 0;
var time = null;

那么,理论上,由此该返回以下函数。

return function (modelArg) {
    options.process.call(options.thisArg, count - 1, modelArg);
    return true;
};

显然,在上述返回的函数中,在调用该绑定的方法前,我们应当先校检查上次执行的时间,以确定是否应该执行,同时记录本次执行的时间。

var timespan = time != null ? new Date().getTime() - time.getTime() : null;
time = new Date();
if (timespan == null || timespan > options.timeout) {
    count = 1;
    return false;
}

同理,对本轮执行的次数也需要检验和递增。

count++;
var start = !!options.start ? options.start : 0;
if (count < start || (options.count != null && options.count <= count - start)) return false;
最后,别忘了在函数前加上为空判断。

if (!options || !options.process || options.count === 0) return null;

于是,我们就得到了以下代码。

/**
  * Generates a multiple hit task.
  * @param options  The options to load.
  */
function multipleHit(options) {
    if (!options || !options.process || options.count === 0) return null;
    if (!options.start && options.count == null) {
        return function (modelArg) {
            options.process.call(options.thisArg, 0, modelArg);
            return true;
        };
    }
 
    var count = 0;
    var time = null;
    return function (modelArg) {
        var timespan = time != null ? new Date().getTime() - time.getTime() : null;
        time = new Date();
        if (timespan == null || timespan > options.timeout) {
            count = 1;
            return false;
        }
 
        count++;
        var start = !!options.start ? options.start : 0;
        if (count < start || (options.count != null && options.count <= count - start)) return false;
        options.process.call(options.thisArg, count - 1, modelArg);
        return true;
    };
}

现在我们来测试一下。把以下代码放到页面加载之后。

    var task = multipleHit({
        timeout: 300,
        start: 3,
        count: 100,
        process: function (index, model) {
            console.debug(index.toString() + " at " + model);
        }
    });
    document.body.addEventListener("click", function (ev) {
            task(new Date().toLocaleDateString());
        }, false);

当你在页面中快速点击,你会在浏览器控制台中看到,只有快速连击3以上才会显示记录,当出现了100次之后,就不会再有了,除非停一会儿,那就又重新开始计算了。


文章类型及复杂度:Web 进阶。

节选翻译自 MSDN 博文 Multiple Hit Task,内容有所调整。

http://blogs.msdn.com/b/kingcean/archive/2016/03/21/multiple-hit-task.aspx


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值