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 = trueconsole.log(flag1.current,'flag1.current')},2000)}

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

使用setInterval遇到的陷阱相关推荐

  1. Javascript中的陷阱大集合【译】

    参考:http://www.2cto.com/kf/201111/111203.html 昨天晚上在自己的个人技术博客上翻译了一篇有关Javascript的文章,今天想想还是把它投稿到博客园吧,大家可 ...

  2. React 中闭包陷阱问题分析

    背景 我在现在这家公司,一直都是用 React 做开发的,对 React 的闭包陷阱也有一定的了解,但是要我解释为什么会有闭包陷阱这个问题,也知道解决闭包的方式,就是 setState 的时候,传一个 ...

  3. 五种 Ajax 反模式:避免常见的 Ajax 代码陷阱!

      developerWorks 中国  >  XML | Web development  > Ajax 和 XML: 五种 Ajax 反模式 避免常见的 Ajax 代码陷阱 文档选项 ...

  4. 爬虫漫游指南:瑞数的反调试陷阱

    爬虫漫游指南 瑞数的反调试陷阱 遇上有反爬的网站,第一反应肯定是要先打开开发者工具调试一波,于是,反爬工程师们就在此处设下了第一道防线.初级一点的,例如监听F12,禁用鼠标右键,作为防线的一部分,这些 ...

  5. setTimeout、setInterval、promise、async/await的顺序详解(多种情况,非常详细~)

    本文很长,列举的情况很多. 在阅读本文之前,如果您有充足的时间,请新建一个项目与本文一同实践. 每段代码都有对应的解释,但是自己动手尝试印象才会更深哦~ setInterval:表示多久执行一次,需要 ...

  6. Golang 要注意的陷阱和常见错误

    原文: 50 Shades of Go: Traps, Gotchas, and Common Mistakes for New Golang Devs 翻译: Go的50度灰:新Golang开发者要 ...

  7. html里的swal添加倒计时,使用甜蜜警报插件的setInterval函数倒计时

    我试图实现倒计时到sweetAlert.在不活动20分钟后,会弹出甜蜜警报并显示会话即将超时,并且用户有两种选择:注销或继续,这将重新启动空闲计时器.当鼠标移动或点击时,空闲计时器也会重置.我的问题是 ...

  8. typedef的四个用途和两大陷阱

    typedef的四个用途和两个陷阱 --------------------------------- 用途一: 定义一种类型的别名,而不只是简单的宏替换.可以用作同时声明指针型的多个对象.比如: c ...

  9. Window对象中setInterval()和setTimeout()的区别

    - setInterval("",time):每隔指定的时间执行一次调用的函数或计算表达式,如果不停止会无限次去执行: - setTimeout("",time ...

最新文章

  1. matlab中real函数,Matlab中del2()函数学习笔记
  2. mysql mtq_mysql基本操作 - osc_r3mtqivi的个人空间 - OSCHINA - 中文开源技术交流社区
  3. 学用 ASP.Net 之 System.Collections.Specialized.CollectionsUtil 类
  4. 机器学习导论(张志华):正定核应用
  5. maven编译不通过:软件包com.sun.org.apache.xml.internal.security.utils.Base64 不存在
  6. 使用 Karma、Mocha、Chai 搭建支持 ES6 的测试环境
  7. 电子设计竞赛电源题(1)-电源题简介
  8. 从一个数组中找出最接近目标_LeetCode每日一题 | 转变数组后最接近目标值的数组和...
  9. 计算机发展初期 承载信息的媒体,兰州大学《多媒体技术基础》18秋平时作业3(含答案)...
  10. 【论文分享】ACL 2020 细粒度情感分析方法
  11. 程序员有多少读过《人性的弱点》?项目经理呢?
  12. html自动浮动div广告,div+css下js浮动对联广告不随屏幕滚动的解决方法
  13. oracle exadata效果,exadata成功案例与性能测试-oracle.pdf
  14. 初学编程:算法编程是什么意思?盘点最常用的 5 大算法!
  15. Dreamweaver开发人员工作区 标准工作区的区别
  16. dialog在关闭的时候会刷新页面,并且地址后面多加了一个问号,导致数据查询不出来的解决方法
  17. MT8665原理图芯片资料介绍
  18. EMACS 使用手册
  19. SFP光模块电气接口参数详解
  20. 新版PF使用说明文档

热门文章

  1. jetson nano的a02与b01混用
  2. C++中static变量的初始化
  3. Android集成开发工具——Android Studio
  4. org.apache.axis2.AxisFault: test.super.com
  5. 美好如祈而至,古乐祈赋能珠宝品牌正式发布!
  6. 计算机中级职称能转评讲师,职称评定中,什么是同级转评?
  7. Kali木马免杀,权限提升(kali本地木马免杀)
  8. VMware虚拟机安装Windows2003 详细过程
  9. php 值转移,迁移与数据填充 - Migrations Seeding
  10. 质因数的求解(C语言和C++)