[JavaScript面试题]倒计时,倒数

328 阅读2分钟

倒计时

使用js元素写倒计时模块,当写的第一反应下是使用for循环包裹一个计算器进行计算。但是这样忽略了同步与异步直接的联系

<script>
     let time = document.querySelector('.time')
     let input = document.querySelector('.input')
     let btn = document.querySelector('.btn')
    btn.onclick=function () {
         if(input.value>0) {
             time.innerText = input.value
             for(i=time.innerText;i>0,i--){
                setTimeout(() => {
                   console.log(time.innerText--)// 此时time.innerText为5
                },1000);
             }
         }else{
             alert('输入正确内容')
         }
     }
  </script>

当将计时器放进for循环后,因为setTimeout作为异步代码,会在代码执行时进入异步队列进行等待,而此时for为同步代码在持续执行循环,直到结束循环。而当for循环结束时,此时在异步队列中,已经存在n个setTimeout,此时时间一到,所有的setTimeout函数执行,time.innerText--进行n次--,输出结果为倒叙的5,4,3,2,1

image-20220318204259795.png

虽然达到呢递减的效果,但是因为在异步队列中,所有的setTimeout函数都是在1000毫秒后的条件下触发,所以所有的数据都是在1000毫秒内执行完毕,并没有达到倒计时的效果。

这时,了解了setTimeou在for中的作用后,我们换一种方法进行

在HTML中不只有setTimeout还有setInterval,setInterval的作用是在指定的间歇时间内不断的循环内部的操作

比如

setTimeout(function(){ alert("Hello"); }, 3000);

当执行这段代码时,会不断的在3000毫秒后弹出Hello。居然能够间歇执行函数,那么是否能够解决使用setTimeout进入异步队列后一次性完成全部队列的问题。

代码如下

 <script>
     let time = document.querySelector('.time')
     let input = document.querySelector('.input')
     let btn = document.querySelector('.btn')
    btn.onclick=function () {
         if(input.value>0) {
             time.innerText = input.value // 此时time.innerText为5
         }else{
            alert('输入正确数字')
         }
         var cle = setInterval(() => {                                     
             console.log(time.innerText--);   
            },1000);
     }
  </script>

这样,代码就会进行间隔执行,没间隔一秒钟执行一次time.innerText--,但是这是输出的值又出行了问题

image-20220318211630860.png

setInterval会不断执行,并且不会停止,time.innerText--一直执行,成为负数依然还在--。

此时可能就会说了,我给setInterval设定条件,当time.innerText--到0时停止执行。看起来好像没问题,但是在函数中,setInterval是不会被其他条件打断的,只要执行其会一直执行下去。所以这是出现了clearInterval。

clearInterval() 方法可取消由 setInterval() 函数设定的定时执行操作。

clearInterval() 方法的参数必须是由 setInterval() 返回的 ID 值。

注意: 要使用 clearInterval() 方法, 在创建执行定时操作时要使用全局变量:

使用clearInterval完成倒计时,代码如下

</head>
  <body>
    <div>
      <i class="time">0</i>
      <input type="text" placeholder="输入整数" class="input" />
      <button class="btn">开始倒计时</button>
    </div>
  </body>
 
 <script>
     let time = document.querySelector('.time')
     let input = document.querySelector('.input')
     let btn = document.querySelector('.btn')
     var cle = null // 设置这个变量是为了获取setInterval的id
    btn.onclick=function () {
         if(input.value>0) {
             time.innerText = input.value
         }else{
            alert('输入正确数字')
         }
          cle = setInterval(() => {                                     
             console.log(time.innerText--);
               if(time.innerText==0){
                clearInterval(cle)
            }       
            },1000);
            
     }
  </script>