js中的setTimeout和setInterval到底有啥区别?

最近在写小程序和蓝牙交互时,由于数据包可能会受到干扰,用到重发机制,所以需要js中的延时方法。我们知道js中的延时加载有两个方法分别是setTimeout和setInterval,这两个方法有啥差别呢?

1. setTimeout的使用方法

setTimeout allows to run a function once after the interval of time.

在延时后的只执行一次

setTimeout(func|code, delay[, arg1, arg2...])

Function or a string of code to execute. Usually, that’s a function. For historical reasons, a string of code can be passed, but that’s not recommended.

func可以是方法,也可以是String,但是官方文档中说,String这种方式不建议使用。

1.1 setTimeout方法使用不带参数使用

function sayHi() {
  alert('Hello');
}

setTimeout(sayHi, 1000);

1.2 setTimeout方法带参数方法的使用

function sayHi(phrase, who) {
  alert( phrase + ', ' + who );
}

setTimeout(sayHi, 1000, "Hello", "John"); // Hello, John

注意:下面这样写是错误的,我就被坑了

function sayHi(phrase, who) {
  alert( phrase + ', ' + who );
}

setTimeout(sayHi(), 1000,"Hello", "John");

这样写会报 undefined,undefined.

其实这样写,自己想一下,也知道不会执行的。sayHi()这个方法并没有返回值,所以1000ms后也不会执行。

扫描二维码关注公众号,回复: 2494299 查看本文章

2.setInterval 方法的使用

setInterval allows to run a function regularly with the interval between the runs.
这个方法会在指定的延时间隔重复执行。

let timerId = setInterval(func|code, delay[, arg1, arg2...])

2.1使用方法

// repeat with the interval of 2 seconds
let timerId = setInterval(() => alert('tick'), 2000);

// after 5 seconds stop
setTimeout(() => { clearInterval(timerId); alert('stop'); }, 5000);

3.在延时执行函数需要知道的细节

首先我总结一下:

setTimeout会保证在指定好的延时时间后执行,但是setInterval则不会这样。
如果function中的代码有耗时载操作,那么使用setTimeout方法递归,则可能会增加总递归的时间。
而使用setInterval方法,如果程序中耗时比延时间隔长,则会立刻回调函数。

先看一下官方的说明

3.1 setInterval方法

let i = 1;
setInterval(function() {
  func(i);
}, 100);

这里写图片描述

The real delay between func calls for setInterval is less than in the code!

That’s normal, because the time taken by func’s execution “consumes” a part of the interval.

It is possible that func’s execution turns out to be longer than we expected and takes more than 100ms.

In this case the engine waits for func to complete, then checks the scheduler and if the time is up, runs it again immediately.

In the edge case, if the function always executes longer than delay ms, then the calls will happen without a pause at all.

3.2 setTimeout方法

let i = 1;
setTimeout(function run() {
  func(i);
  setTimeout(run, 100);
}, 100);

这里写图片描述

The recursive setTimeout guarantees the fixed delay (here 100ms).

That’s because a new call is planned at the end of the previous one.

3.3我自己写了一个测试案例,也说明了这一点。

<!DOCTYPE html>
<html>
<head>
    <title>测试</title>
</head>
<body>  
<table>

<button onclick="test()">start</button>
  <tr>
    <th>type</th>
    <th>calls</th>
    <th>seconds</th>
    <th>average calls/second</th>
  </tr>
  <tr id="i">
    <td>setInterval</td><td>0</td><td>0</td><td>0</td>
  </tr>
  <tr id="t">
    <td>setTimout</td><td>0</td><td>0</td><td>0</td>
  </tr>

</table>

        <script type="text/javascript">
        function test (){

        var speed = 2000
        var start = +new Date
        var icounter = 0
        var tcounter = 0
        var i = document.querySelector('#i')
        var t = document.querySelector('#t')
        setInterval(function () {
          var time = (new Date - start) / 1000
          var avg  = icounter++ / time
          i.innerHTML = '<td>setInterval</td><td>' + icounter + '</td><td>' + time.toFixed(3) + '</td><td>' + avg.toFixed(6) + '</td>'
        }, speed)
        function e () {
          var time = (new Date - start) / 1000
          var avg  = tcounter++ / time
          t.innerHTML = '<td>setTimout</td><td>' + tcounter + '</td><td>' + time.toFixed(3) + '</td><td>' + avg.toFixed(6) + '</td>'
          setTimeout(e, speed)
        }
        setTimeout(e, speed)

        }
        </script>   
</body>
</html>

执行结果如下

这里写图片描述

好了分析到这里,具体这两个延时你使用哪一个,相信你心里已经很清楚了。
因为我在蓝牙项目中,需要确定的间隔去发送数据,所以我采用了setTimeout这个方法去循环发送数据。

猜你喜欢

转载自blog.csdn.net/qdh186/article/details/81129727