JavaScript 定时器关键点及使用场景解析

2023-02-01 09:10:31
目录
正文关于计时器的关键点异步函数setTimeoutsetInterval区别使用场合总结

正文

JavaScript>setTimeout 和 setInterval 。接下来看看有哪些定时器以及它们是如何工作的。

关于计时器的关键点

在深入了解定时器的具体细节之前,有几个非常关键的点需要记住。

并不完全准确

定时器要么在一定秒数后触发一个动作,要么在每次指定的超时结束时重复一个动作。但是,尽管期望可能是它们精确到秒,但事实并非如此。

这些计时器的规范声明它们将使用时间参数(如指定的秒数)作为最短等待时间。但如果还有其他任务需要先完成,它们肯定会花费更长的时间。

只有当你逻辑依赖于精确的时间测量时,这才会成为问题,比如让时钟通过>setInterval 回调来计算秒数。

异步函数

这意味着它们在完成之前不会停止程序流。即使指定>0 作为超时值,它们的行为仍然是异步的。

这意味着这些函数会将对想要触发的函数的引用添加到事件循环中,所以即使在超时值上指定了 0,引用也会在接下来发生的所有事情之后排队。

setTimeout

setTimeout>

这个函数参数如下:

    要执行的函数引用:这是时间一到就会触发的代码逻辑。函数执行前的等待的秒数然后所有其他参数以相同的顺序传递给执行的函数。

    下面的代码将在 3 秒后打印 Hello World

    setTimeout(console.log, 3000, "Hello", "World");
    

    等效于以下代码:

    setTimeout(
        (strHello, strWorld) => {
            console.log(strHello, strWorld);
        },
        3000,
        "Hello",
        "World"
    );
    

    setTimeout 是一种特殊类型的异步函数,因此无论在其后编写什么代码,都将在触发该函数之前执行,如下:

    console.log("执行了第 1 行代码");
    setTimeout(() => {
        console.log("执行了第 3 行代码");
    }, 1000);
    console.log("执行了第 5 行代码");
    console.log("执行了第 6 行代码");
    setTimeout(function () {
        console.log("执行了第 8 行代码");
    }, 0);
    console.log("执行了第 10 行代码");
    

    输出的结果如下:

    执行了第 1 行代码
    执行了第 5 行代码
    执行了第 6 行代码
    执行了第 10 行代码
    执行了第 8 行代码
    执行了第 3 行代码

    请注意第 3 行和第 8 行是如何最后执行的,即使第 8 行的超时为 0

    在讨论 setTimeout 之前,如果设置超时值然后意识到必须停止它会发生什么?可以定义一个变量保存 setTimeout 的返回值(计时器 ID),则可以使用 clearTimeout 函数在超时之前停止计时器。

    console.log("执行了第 1 行代码");
    const timerId = setTimeout(() => {
        console.log("执行了第 3 行代码");
    }, 1000);
    console.log("执行了第 5 行代码");
    clearTimeout(timerId);
    console.log("执行了第 6 行代码");
    setTimeout(function () {
        console.log("执行了第 8 行代码");
    }, 0);
    console.log("执行了第 10 行代码");
    

    执行结果如下,少了一个定时器的输出:

    执行了第 1 行代码
    执行了第 5 行代码
    执行了第 6 行代码
    执行了第 10 行代码
    执行了第 8 行代码

    setInterval

    setInterval>setTimeout 非常相似,但它不是只触发一次函数,而是一直触发函数直到停止。

    此函数的签名与 setInterval 函数的签名完全相同,所有参数的也相同。

    const names = ["刘备", "关羽", "张飞", "赵云", "黄忠"];
    function sayHi(list) {
        let name = list[Math.round(Math.random() * 10) % 4];
        console.log("你好!", name);
    }
    console.log("蜀汉五虎将");
    const intervalID = setInterval(sayHi, 1000, names);
    setTimeout(() => {
        clearTimeout(intervalID);
    }, 4000);
    

    上面的代码将启动一个每 1 秒触发一次的循环,当它触发时,将选择一个随机名称并打印字符串 你好! <name>。设置了 4 秒的超时时间,通过调用 clearTimeout 函数来结束无限循环。当然,也可以使用 clearInterval 函数,但由于它们使用相同的计时器池,可以互换使用它们。

    区别

    setTimeout>setInterval 在给定的时间间隔后保持定期触发表达式(除非手动终止)。

    使用场合

    除了执行定时操作,结合>Promise 方法,结合 setTimeout 可以实现休眠功能。

    const sleep = (ms) => {
        return new Promise((resolve) => setTimeout(resolve, ms));
    };
    const asyncFoo = async () => {
        await sleep(2000);
        console.log("  等待2秒输出");
        await sleep(1000);
        console.log("    等待1秒输出");
    };
    console.log("开始执行");
    asyncFoo();
    

    Promise 结合 setInterval 可以实现一些数据的最大检测次数,如某个数据通过API验证,验证结果无法给出正常结果,超过一定次数提示错误。

    const fakeApiCheck = async () => {
        console.log("检查中...");
        return Math.random() > 0.8;
    };
    const asyncInterval = async (callback, ms, triesLeft = 5) => {
        return new Promise((resolve, reject) => {
            const interval = setInterval(async () => {
                if (await callback()) {
                    resolve();
                    clearInterval(interval);
                } else if (triesLeft <= 1) {
                    reject();
                    clearInterval(interval);
                }
                triesLeft--;
            }, ms);
        });
    };
    const dataCheck = async () => {
        try {
            await asyncInterval(fakeApiCheck, 500);
        } catch (e) {
            console.log("验证错误");
        }
        console.log("验证完成!");
    };
    dataCheck();
    

    总结

    计时器是生成重复或延迟行为的绝佳函数,它们非常有用,尤其是当必须在某些基于时间的条件下与其他服务进行交互时。超时和间隔都可以在使用>clearInterval 或者 clearTimeout 函数触发之前强制停止。

    以上就是JavaScript 定时器关键点及使用场景解析的详细内容,更多关于JavaScript 定时器的资料请关注易采站长站其它相关文章!