咱们都知道的是setTimout
是用来延迟一个简单的动做的,然而,setInterval
的目的是用来重复执行某个动做的。php
而后,以上只是一半的事实。由于若是一个函数须要在一个间隔时间内重复的执行,你也能够轻松的使用 setTimeout
设定延迟时间,被延迟执行的函数再进行自调用以此实现循环。ajax
因此,这里有2种方法作一样的事浏览器
一个用setInterval
服务器
var doStuff = function () { // Do stuff }; setInterval(doStuff, 1000);
一个用setTimeout
函数
var doStuff = function () { // DoStuff setTimeout(doStuff, 1000); }; setTimeout(doStuff, 1000);
// 若是你想当即执行函数,能够这样写 var doStuff = function () { setTimeout(doStuff, 1000); } doStuff();
// 或者,更酷的方式,使用当即执行函数 (function doStuff () { // Do Stuff setTimeout(doStuff, 1000); }())
这必然致使下面两个问题oop
问题:setInterval
和self-invoking setTimeout-loops
是能够互相替换的吗?
答案:不,固然不行。它们之间有着很细微的区别,可是若是想写出好的代码,这些细微的区别即是你想知道的事。网站
固然,接下我将会诉说的,第一,我将告诉你,咱们一般会遇到什么样的问题,第二,我将开始介绍它们之间细微的区别,这些区别将让咱们从这两个选择中选出更具吸引力的那个一,第三,我将告诉你其实根本不用关心另外一个。而后。这里是结论,setTimeout
将是更惊艳的那一个。接下来我将一点一点解释。ui
首先:若是你试着重复调用的函数并不会化太多的时间来跑,那么将不会有任何问题。即便如此,被调用的函数依然会出现2中不一样的状况:它既能够在CPU上高集中的运行脚本,或者它也能够在脚本流外先发出一个命令,并等待结果的到来。this
咱们主要研究先看第二种状况。典型的即是ajax回调:你的脚本并不会等待服务器的响应,它会本身执行到最后,并让回调函数来监听ajax响应。code
如今,一些网站想要你保持实时更新,像Gmail,当你得到一封新的邮件时便会刷新你的邮箱。这里服务端有新消息时便实时通知浏览器端的技术,一般叫作ajax轮询。浏览器隔一段时间像服务器发送一个请求,询问这里有没有须要更新的消息。
你也许会想,你很擅长使用setInterval
// 不要这样作 var pollServerForNewMail = function () { $.getJSON('/poll_newmail.php', function (response) { if (response.newMail) { alert( "New mail. At last. You made me walk all the way to the server and back every " + "second for this, so if this isn't life-or-death, you got another thing coming." ); } }); }; setInterval(pollServerForNewMail, 1000);
其实像上面那样写并很差。由于请求发送出去到回来是须要时间的,可是这段时间谁能保证会比你设置的间隔时间要短呢?
一个典型的初学者的错误,会想将轮询的间隔时间设置的长一点也许能够解决这个问题。而后,事实是,不管你的间隔时间设的是多少,它依然有可能比,ajax响应的时间短。也就是说,有可能会发生,第一个请求还没回来的状况下,第二请求又已经发出去了。而你须要的是两个请求之间有呼吸的空间,而setTimeout
即可以解决这个问题。
(function pollServerForNewMail() { $.getJSON('/poll_newmail.php', function (response) { if (response.newMail) { alert( "You have received a letter, good sir. " + "I will have a quick lie-down and be on my way shortly." ); } setTimeout(pollServerForMail, 1000); }); }());
在第一次发出请求,服务器响应以前,不会发生任何事。在响应回来时,才会继续发出第二个请求。固然,这也就意味着,两个轮询之间的时间超过了1秒,这也依赖于各类各样的因素,像网速和服务器的响应速度等。可是,显然的,这对咱们要作的事来讲并不算是什么问题。
这里有两个例子来更好的进行说明。
var timesRun = 0; var startTime = new Date().getTime(); var doStuff = function () { var now = new Date().getTime(); // 只跑5次 if (++timesRun == 5) clearInterval(timer); console.log('Action ' + timesRun + ' started ' + (now - startTime) + 'ms after script start'); // Waste some time for (var i = 0; i < 100000; i++) { document.getElementById('unobtanium'); } console.log('and took ' + (new Date().getTime() - now) + 'ms to run.'); }; var timer = setInterval(doStuff, 1000);
下面是结果
Action 1 started 1000ms after script start and took 8ms to run. Action 2 started 2000ms after script start and took 8ms to run. Action 3 started 3004ms after script start and took 6ms to run. Action 4 started 4002ms after script start and took 6ms to run. Action 5 started 5000ms after script start and took 6ms to run.
这里并无多大的意外。这段代码中间的循环花了一点时间,可是setInterval
依然很严格的执行了它的计划。在一秒的间隔之间,开始时间之间并无一点空隙。
如今是setTimeout-loop
的例子
var timesRun = 0; var startTime = new Date().getTime(); var doStuff = function () { var now = new Date().getTime(); console.log('Action ' + (timesRun + 1) + ' started ' + (now - startTime) + 'ms after script start'); // Waste some time for (var i = 0; i < 100000; i++) { document.getElementById('unobtanium'); } console.log('and took ' + (new Date().getTime() - now) + 'ms to run.'); // Run only 5 times if (++timesRun < 5) { setTimeout(doStuff, 1000); } }; setTimeout(doStuff, 1000);
输出结果
Action 1 started 1010ms after script start and took 8ms to run. Action 2 started 2021ms after script start and took 8ms to run. Action 3 started 3031ms after script start and took 5ms to run. Action 4 started 4037ms after script start and took 6ms to run. Action 5 started 5043ms after script start and took 6ms to run.
这里也并无太多的意外。咱们已经知道setTimeout-loop
并不会严格的执行计划,而是在函数下一次调用以前,会给函数它足够的时间执行它里面的代码。
不要使用setInterval
,若是你在意你的时间。setTimeout-loop
能够给你足够的时间控制你的脚本和回调,