定时循环输出状态机 setTimeout setInterval

360 阅读2分钟

背景

最近接到一个需求是需要循环轮播一个动画,这个需求还是蛮常见的,关键的动画逻辑是需要一个循环的定时器,持续的输出 0 1 2 3,然后重新开始循环下去,这里是一些思路总结

循环输出的应用场景

  • 轮播场景
  • 定时循环

实现思路

基础版本1 -- 单次循环 for + var + setTimeout

需求1: 每隔1s循环输出0 1 2 3 ...

for (var i = 0; i < 4; i++) {
    setTimeout(function(t) {
        console.log(i);
        // do sth...
    }, i * 1000, i);
}
// 输出
0
1
2
3

基础版本2 -- 定时循环 for + setTimeout + setInterval

需求2: 定时循环实现
1.首次执行一次 0 1 2 3
2.等待上一次setTimeout执行完毕,开始定时器执行setInterval

// done回调函数来控制一次循环结束
function loop (done) {
    for (var i = 0; i < 4; i++) {
        setTimeout(function(i) {
            console.log(i);
            // do sth...
        }, i * 1000, i);
        
        if (i === 3 && done) {
            done()
        }
    }
}
// 第一次先执行一遍 0 1 2 3
// 第二次等待执行完毕之后 再去setInterval循环 这里使用done回调函数来告知第一遍执行完了
loop(function(){
    // 等待第一次setTimeout执行完开始第二次循环...
    setInterval(function(){
        loop();
    }, 4000)
});

//输出
0 1 2 3
0 1 2 3
...

进阶版本 -- 定时器 + 计数器 setInterval

var count = 0;
setInterval(function(){
    console.log(count);
    // do sth...

    count++;
    if (count > 3) {
        count = 0;
    }
},1000);

//输出
等待1s后
0 1 2 3
0 1 2 3
...

缺点: 一进来需要先等个1s,我们希望一进来就执行一次

最终版本 -- 立即执行 + 定时器 + 计数器 setIntervalImmediately

var count = 0;
var loopInterval;

var loop = function () {
    console.log(count);
    // do sth...

    count++;
    if (count > 3) {
        count = 0;
    }
}
var setIntervalImmediately = function(func, interval) {
    func();
    return setInterval(func, interval);
}
loopInterval && clearInterval(loopInterval);
loopInterval = setIntervalImmediately(loop, 1000);
//输出
不需要等待1s,
直接执行
0 1 2 3
0 1 2 3
...

我正在参与掘金技术社区创作者签约计划招募活动,点击链接报名投稿