使用setInterval遇到的陷阱

2023-05-16

setInterval的使用

const interval = setInterval(() => {
     //循环代码
     console.log('执行一次')
     if (...){
         clearInterval(interval)
       }
}, 2000)

常规使用方式如上,每隔2s执行一次,当条件成立时执行clearInterval(interval)阻断循环

解决setInterval的使用中不立即执行问题

使用setInterval是为了让某段程序定时循环执行,但是setInterval的执行机制是第一次不执行,间断设定的时间之后才执行。解决这个问题,最简单的方法就是在使用setInterval之前首先执行一次,但是这样的方式在代码简单时还好,循环的代码复杂时会带来代码冗余的问题,所以可以采用如下方式:

setInterval(function fun() {
  //循环代码
  console.log('执行')        
  return fun //注意需要在函数中返回自身,否则只会执行一次
}(), 3000)

在待执行的函数后面加一个小括号,表示立即执行一次,注意这样的用法需要在函数的末尾对函数本身进行返回。

解决使用setInterval异步执行时发送ajax请求带来的问题

setInterval是异步执行的,即:每一次的循环代码相互之间都是独立的,只会在设定的时间到达时立即执行,无论上一次的循环过程是否完成,这样在满足一些使用场景的时候就会带来问题。例如在进行ajax请求的时候,需要根据ajax请求的返回值判断是否继续循环,但是setInterval的每一次循环会直接无视返回值,继续向下执行。
假设场景如下:每隔1s访问如下接口‘/mocktemplate’(该接口每5s返回结果,模拟网络延迟返回结果慢的情况),根据返回的结果flag为true或者false判断是否进行下一次请求,如果使用setInterval,代码如下:

function cycle1() {
        const inter = setInterval(() => {
            console.log('执行了')
            axios.post('/mocktemplate')
                .then(res => {
                    if (res.data.flag) {
                        console.log(res.data.flag, 'res.data.flag')
                        clearInterval(inter)
                    }
                    console.log(res, '执行结果')
                })
        }, 1000)
    }

执行结果如下:
结果展示图
我们需要的效果是返回true之后就停止循环,不再继续,但是由于循环设定是每1s执行一次,而接口返回的时间是5s,导致每一次的循环事件都无视结果按照每1s一次进入到执行队列中,6次循环事件都进入执行队列之后,第一次的ajax请求结果才返回,虽然为true,但还是要把之后的5次已经进入队列的事件执行完成。
所以如果要等待ajax的返回结果返回之后再进行下一次循环请求,就需要使用setTimeout代替setInterval,代码如下:

 function cycle2() {
        setTimeout(() => {
            console.log('执行了')
            axios.post('/mocktemplate')
                .then(res => {
                    if (res.data.flag) {
                        console.log(res.data.flag, 'res.data.flag')
                        return res.data.flag
                    } else {
                        cycle2()
                    }
                    console.log(res, '执行结果')
                })
        }, 1000)
    }

执行结果如下:
执行结果展示图
如图所示,在ajax返回true之前,不会进行向下执行,只是这样做得后果就是:循环执行的周期变成了“原循环周期+ajax请求返回的时间”

解决使用setInterval无限循环

1、需要无限循环的场景
一些使用场景,不希望循环停止,例如对网页进行每半小时刷新一次的操作,直接使用setInterval可以满足使用,但是因为setInterval不会自动清除定时器队列,每循环一次定时器都会叠加一次,无限长时间进行下去,最终会导致网页卡死。但是setTimeout是自带清除定时器的,配合setTimeout使用即可解决卡死的问题。用法如下:

setInterval(()=>{
    setTimeout(()=>{
        console.log('执行一次')
    },0)
},2000)

2、跳转到其他页面时需要清除定时器
在react中使用定时器,用法如下:

useEffect(()=>{
   const timer = setInetrval(()=>{
        fun()
   },5000)
   return ()=>{
       clearInterval(timer)
   }
},[])

即在return里面清除定时器,页面销毁时会调用return的函数
3、实现选择不同的选项进入不同的循环(场景:一个下拉框,当选择不同任务时,触发onChange方法,在onChange方法中根据任务项拉取任务进度)
要解决对的问题:选择第一个任务,触发定时器任务,但是当定时器任务没有执行完毕的时候,再次选择其他的任务项,上一个定时器任务不会停止。可以使用useState对上一次的定时器进行保存。

const [interval,setInterval] = useState()
function onChange(name){
    clearInterval(interval)
    const timer = setInetrval(()=>{
        getWorkFlow(name)
   },5000)
   setInterval(timer)
}

onChange函数刚进来的时候interval保存的仍然是上一次的定时器。

setInterval的闭包陷阱

setInterval和setTimeout无法获取到代码开始执行之后useState变化的值,例如:

const [flow, setFlow] = useState(null)
function cycle4(){
        setInterval(()=>{
            setFlow(true)
            console.log(flow,'flow')
        },2000)
    }

cycle4开始执行之后,得到的flow的值始终是null,因为此时的上下文环境始终是程序开始执行之前的上下文环境,所以检测不到setFlow时flow的变化。
解决方法如下:使用useRef代替:

const flag1 = useRef()
function cycle4(){
        setInterval(()=>{
            flag1.current = true
            console.log(flag1.current,'flag1.current')
        },2000)
    }

此时可以获取到每次值的变化。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用setInterval遇到的陷阱 的相关文章

  • 为什么 setInterval 回调只执行一次?

    我制作了这个计数器 但我希望它永远运行 这非常简单 我在这里做错了什么 function timer console log timer window setInterval timer 1000 您使用函数调用而不是函数引用作为 setI
  • 如何停止“setInterval”[重复]

    这个问题在这里已经有答案了 我该如何停止和开始setInterval 假设我有一个textarea 我想停下来setInterval聚焦并重新启动setInterval模糊 使用 jQuery 你必须存储timer id启动它时的时间间隔
  • “setInterval”内“for”的索引

    我有一个对象 我把它放在一个数组中 然后我用for对于数组中的每个对象 我设置了一个设置的间隔 用于使用参数调用对象的方法 但我不能 这是我的 班级 function ClassTest this test function word co
  • 如何获取自动刷新的日期?

    我正在尝试获取页面上刷新的日期 这样我就不必每天手动刷新它 我有这段代码 但它似乎不起作用 日期会显示 但日期更改时不会更新 作为参考 这是在 BrightSign 显示屏上使用的 谁能告诉我我做错了什么 我是一个 JavaScript 初
  • Typescript:私有成员突然未定义

    所以 我有一个基本的 Typescript 应用程序 它实际上不会引起任何重大问题 但似乎这里出了问题 我不知道是什么 我确实有这个私人会员minUpdateRate in my GameContainer类 在构造函数中初始化 这似乎进展
  • JavaScript:使用 window.setTimeout 触发 CSS 转换

    这 显然 是一个更大项目的一部分 但我正在尝试触发 CS 转换setTimeout 我知道如何使用 CSS 动画 但这不仅仅是重复的过渡 当属性更改时 将发生 CSS 转换 为了我自己的目的 我使用setAttribute因为这将行为与其他
  • 在 Matlab 中每秒打印一次警告

    我试图每秒打印一条警告或仅打印一条消息 例如 已过 1 秒 有可能实现这一点吗 我用 tic toc 和循环尝试过 但还不够 此外 我从来没有得到过一秒钟的时间 是否有一个命令可以每 X 毫秒自动打印一次 有任何想法吗 提前致谢 Use a
  • javascript/jQuery setInterval/clearInterval

    我正在使用 setInterval 来检查 p html 段落 是否具有特定的文本值 如果有的话我想清除间隔并继续代码流 我在 jQuery 插件中使用它 所以如果段落有 tat 文本值 我想清除间隔 然后继续使用回调函数 所以我尝试了这样
  • setinterval() 和clearinterval() - 清除后,不会自动设置动画

    所以我正在尝试构建一个动画背景图像 它将循环显示一组图像 这个想法还在于 当您单击页面上的任何导航元素时 循环将会暂停 当您单击主页按钮时 循环将再次启动 从当前图像开始 这在当前状态下有效 但是重新启动时循环不会自动进行 而是您必须按主页
  • 停止动态生成的setInterval

    我正在生成多个图表 每个图表都有自己的 setInterval 来刷新数据 当动态生成的容器被删除时 我将其设置为clearInterval 但如果我重新加载并且它具有相同的id 则旧的setInterval将继续运行 有没有办法设置一个动
  • Python 线程 - 如何在单独的线程中重复执行函数?

    我有这个代码 import threading def printit print Hello World threading Timer 1 0 printit start threading Timer 1 0 printit star
  • JavaScript 单击功能可启动和停止间隔

    我有两个 onclick 函数 它们使用套接字执行启动和停止功能 当我单击启动时 它开始从服务器请求图像 我正在使用间隔 当我单击停止时 服务器已停止 但请求不断发送到服务器 单击后 间隔似乎没有停止 请检查我的代码 Code var in
  • 了解 JavaScript setTimeout 和 setInterval

    我需要一些帮助来理解和学习如何控制这些功能来完成我想要它们做的事情 基本上 我有 Java 背景 并通过 Pong 游戏 项目深入研究 JavaScript 我已经设法通过 setInteval 每 20 毫秒调用我的主游戏循环来运行游戏
  • 动态更改 setInterval 值

    我想动态更改 setInterval 的间隔值 由于 setInterval 回调函数中存在循环 我正在苦苦挣扎 我在stackoverflow上看到了太多问题 但没有任何解决方案可以帮助我 如果有人知道答案 请举例说明 谢谢 这是我的代码
  • 在 Javascript 中创建循环以与 imap-simple nodejs 包一起使用

    首先 介绍一些关于我的测试脚本将涵盖的内容的背景知识 按网站上的按钮将向测试邮箱发送一封电子邮件 此电子邮件可能需要 10 到 30 分钟才能到达测试邮箱 所以使用以下代码imap 简单 https www npmjs com packag
  • 如何在 karma angularjs 中对 setInterval 进行单元测试

    app directive shuffleBlocks function timeout return link function sco ele att if itemCnt lt 1 return Trigger function fu
  • 使用 Javascript 使用计时器更改背景颜色和文本颜色

    我正在尝试使用计时器更改表格及其所有单元格的背景和文本颜色 我在结束标记之前有下面的脚本 背景是唯一改变的 表的 ID 是 titleTable 谢谢
  • setInterval 似乎不起作用?

    这段代码似乎不起作用 我正在尝试创建一个可用聊天室的动态列表 每 10 秒更新一次 我还希望用户能够设置参数来过滤要显示的房间 我正在使用这段代码 但由于某种原因它似乎不起作用
  • HTML5 + Jscript 与 JQuery、setInterval 问题

    在我把桌子上的所有东西都扔出去之前 请有人告诉我为什么这不起作用 我有以下 html 文档
  • setInterval() 只运行一次函数

    我想定期查询 PHP 脚本以获取新消息 为此 我使用 setInterval 函数和 AJAX document ready function var queryInterval 1000 How fast we query for new

随机推荐

  • moment的startOf、endOf使用

    moment的startOf endOf使用 举例 xff1a 今天的日期 xff1a 2020 04 14 16 41 startOf语法 xff1a moment startOf String 通过将原始的 moment 设置为时单位的
  • 133道Java面试题及答案(面试必看)

    Java 面试随着时间的改变而改变 在过去的日子里 xff0c 当你知道 String 和 StringBuilder 的区别就能让你直接进入第二轮面试 xff0c 但是现在问题变得越来越高级 xff0c 面试官问的问题也更深入 在我初入职
  • JS的test()方法

    解析 解释 xff1a js的test 方法用于检测一个字符串是否匹配某个格式 语法 xff1a RegExpObject test string 返回值 xff1a 如果String中含有RegExpObject中匹配的字符返回true
  • 实时获取当前时间并展示在页面上

    简介 实时获取当前时间并展示在页面上 xff0c 是很多地方常用的 xff1b 在页面中做此展示以便查看时间 本文使用js通过一个小的demo实现效果 完整Code span class token operator lt span spa
  • Visual Studio Code提交代码提示“Make sure you configure your ‘user.name‘ and ‘user.email‘ in git.”

    使用VSCode编译器提交代码到gitlab xff0c 编译器提示 Make sure you configure your 39 user name 39 使用编译器VSCode提交代码到GitLab xff0c 提示 Make sur
  • React编译代码报错提示:React was passed “javascript:;“。

    React编译代码提示报错信息 xff1a React编译代码提示报错信息 xff1a Warning A future version of React will block javascript URLs as a security p
  • 如何添加Iconfont图标到项目及创建新项目?

    1 搜索图标 或者 选择自己上传图标 2 选择图标 xff0c 加入库 3 点击购物车图标 xff0c 如果已经创建项目直接选择点击确定 xff1b 如果没有创建项目点击 43 创建项目 4 输入新项目名称 xff0c 点击确定 5 确定后
  • antd icon 图标组件的使用

    antd提供的icon有限 xff0c 可以直接使用iconfont图标库的图标 1 安装图标组件包 npm install save 64 ant design icons 2 创建图标 import createFromIconfont
  • 字符串解析为指定格式

    将 张三 李四 王五 赵六 解析为 张三 李四 xff08 共4人 xff09 使用 xff1a let str 61 39 张三 李四 王五 赵六 39 empsDeal str 39 张三 李四 共4人 39 方法 xff1a cons
  • 清除redux数据(hooks写法)

    清除redux数据的场景 A页面初始化调用A接口 xff0c 希望在当前页面生效 xff0c 跳转页面不保存数据 xff0c 但redux中已经存有历史数据 xff0c 所以在页面销毁时清除redux数据 A页面请求A接口 useEffec
  • 跳转页面方法

    跳转页面 window location href 61 url 替换当前页面 window location replace url
  • 嵌入式面试总结

    毕业一年多了 xff0c 从事嵌入式开发工作不知不觉也一年多了 xff0c 题主主要从事单片机 xff08 STM32 xff09 应用开发工业类电子方向 xff0c 纯技术涉及到的内容主要是C语言 arm STM32驱动 FreeRTOS
  • 数据库ER图基础概念整理

    ER图分为实体 属性 关系三个核心部分 实体是长方形体现 xff0c 而属性则是椭圆形 xff0c 关系为菱形 ER图的实体 xff08 entity xff09 即数据模型中的数据对象 xff0c 例如人 学生 音乐都可以作为一个数据对象
  • 如何成为一个全能的机器人工程师

    大疆技术总监 xff1a 如何用六年成为一个全能的机器人工程师 机器人学的核心问题是做好和物理世界的交互 现在主流的机器人学分支里 xff0c 处理与物理世界的交互的学科分为三类 xff1a 传感器和处理算法 xff1b 多刚体系统动力学控
  • 任务调度算法

    可实现在单片机裸机下还能有很好的实时性 任务调度器 SCHEDULER TASK scheduler tasks 61 amp P loop 1000Hz 1000 0 0 amp P loop 500Hz 500 0 0 amp P lo
  • 阿里云云计算ACP学习(一)---弹性计算

    弹性计算 1 ECS的概念与定位 概念 xff1a 云服务器ECS xff08 Elastic Compute Service xff09 是一种可弹性伸缩的计算服务 xff0c 可以帮助降低IT成本 xff0c 提升运维效率 xff0c
  • 阿里云云计算ACP学习(二)---弹性存储

    弹性存储 1 阿里云盘古 盘古 飞天底层同一存储平台 盘古的优势 xff1a 盘古系统在一个核心基础层之上 xff0c 通过为不同应用场景而抽象的适配层设计 xff0c 提供了分布式块存储系统和分布式文件系统两种形态 xff0c 基于这一套
  • HDFS读写流程介绍,HDFS读数据和写数据的原理是什么?

    Client 客户端 对HDFS中的数据进行读写操作 xff0c 分别是Client从HDFS中查找数据 xff0c 即为Read 读 数据 Client从HDFS中存储数据 xff0c 即为Write 写 数据 下面我们对HDFS的读写流
  • VIM简单配置step by step

    0 更新vim 更新和安装vim xff0c 保证版本 gt 61 8 0即可 可按照如下命令安装 0 1 安装依赖 yum update y yum install epel release y yum install y git gcc
  • 使用setInterval遇到的陷阱

    setInterval的使用 span class token keyword const span interval span class token operator 61 span span class token function