Heim > Web-Frontend > js-Tutorial > Einführung in die Verwendung von Timer-Funktionen in js (mit Code)

Einführung in die Verwendung von Timer-Funktionen in js (mit Code)

不言
Freigeben: 2018-08-22 14:41:42
Original
3791 Leute haben es durchsucht

Dieser Artikel bietet Ihnen eine Einführung in die Verwendung von Timer-Funktionen in js (mit Code). Ich hoffe, dass er für Freunde hilfreich ist.

1. setTimeout()

Die Funktion setTimeout wird verwendet, um die Anzahl der Millisekunden anzugeben, nach denen eine Funktion oder ein bestimmter Code ausgeführt wird. Es gibt eine Ganzzahl zurück, die die Timer-Nummer darstellt und zum späteren Abbrechen des Timers verwendet werden kann.

var timerId = setTimeout(func|code, delay)
Nach dem Login kopieren

Im obigen Code akzeptiert die setTimeout-Funktion zwei Parameter. Der erste Parameter func|code ist der Name der Funktion oder eines Codeabschnitts, der verzögert werden soll, und der zweite Parameter „delay“ ist die Anzahl der Millisekunden die Ausführung verzögern.

Es ist zu beachten, dass der Code zum Verzögern der Ausführung in Form einer Zeichenfolge in setTimeout eingefügt werden muss, da die Engine die Eval-Funktion intern verwendet, um die Zeichenfolge in Code umzuwandeln. Wenn es sich bei der verschobenen Ausführung um eine Funktion handelt, können Sie den Funktionsnamen direkt in setTimeout einfügen. Einerseits hat die Eval-Funktion Sicherheitsbedenken, und andererseits hat die setTimeout-Methode normalerweise die Form eines Funktionsnamens, um der JavaScript-Engine die Optimierung des Codes zu erleichtern, wie unten gezeigt.

function f(){ 
 console.log(2);
}
setTimeout(f,1000);
// 或者
setTimeout(function (){
console.log(2)
},1000);
Nach dem Login kopieren

Wenn der zweite Parameter von setTimeout weggelassen wird, ist dieser Parameter standardmäßig auf 0 gesetzt.

Zusätzlich zu den ersten beiden Parametern ermöglicht setTimeout auch das Hinzufügen weiterer Parameter. Sie werden an die verzögerte Funktion (Callback-Funktion) übergeben.

setTimeout(function(a,b){  
console.log(a+b);
},1000,1,1);
Nach dem Login kopieren

Im obigen Code hat setTimeout 4 Parameter. Die letzten beiden Parameter werden als Parameter der Callback-Funktion verwendet, wenn die Callback-Funktion nach 1000 Millisekunden ausgeführt wird.

IE9.0 und niedriger erlauben setTimeout nur zwei Parameter und unterstützen keine weiteren Parameter. Derzeit gibt es drei Lösungen. Die erste besteht darin, die Rückruffunktion mit Parametern in einer anonymen Funktion auszuführen und dann die anonyme Funktion in setTimeout einzugeben.

setTimeout(function() {
  myFunc("one","two", "three");
}, 1000);
Nach dem Login kopieren

Im obigen Code ist myFunc die Funktion, die die Ausführung wirklich verzögern möchte und über drei Parameter verfügt. Wenn Sie setTimeout direkt eingeben, können niedrigere Versionen des IE keine Parameter annehmen, sodass Sie es in eine anonyme Funktion einfügen können.

Die zweite Lösung besteht darin, die Bindungsmethode zu verwenden, um die zusätzlichen Parameter an die Rückruffunktion zu binden und eine neue Funktionseingabe setTimeout zu generieren.

setTimeout(function(arg1){}.bind(undefined, 10), 1000);
Nach dem Login kopieren

Im obigen Code ist der erste Parameter der Bindungsmethode undefiniert, was bedeutet, dass diese der ursprünglichen Funktion an den globalen Bereich gebunden ist, und der zweite Parameter ist der Parameter, der an das Original übergeben werden soll Funktion. Bei der Ausführung wird eine neue Funktion zurückgegeben, die keine Parameter benötigt.

Die dritte Lösung besteht darin, setTimeout anzupassen und die apply-Methode zu verwenden, um Parameter in die Callback-Funktion einzugeben.

<!--[if lte IE 9]>
<script>(function(f){
window.setTimeout =f(window.setTimeout);
window.setInterval =f(window.setInterval);
})(function(f){
return function(c,t){
var a=[].slice.call(arguments,2);
returnf(function(){
c.apply(this,a)},t)}});
</script>
<![endif]-->
Nach dem Login kopieren

Zusätzlich zu Parameterproblemen gibt es bei setTimeout noch etwas anderes zu beachten: Wenn die durch setTimeout verzögerte Rückruffunktion eine Methode eines Objekts ist, dann verweist das Schlüsselwort this in der Methode stattdessen auf die globale Umgebung des Objekts, in dem es definiert wurde.

var x = 1;
var o = { 
 x: 2,  y: function(){
    console.log(this.x);
  }
};
setTimeout(o.y,1000);
Nach dem Login kopieren

Ausgabeergebnis: 1

Der obige Code gibt 1 statt 2 aus, was bedeutet, dass dieser von o.y nicht mehr auf o, sondern auf die globale Umgebung zeigt.

Sehen Sie sich ein weiteres Beispiel an, bei dem Fehler nicht leicht zu finden sind.

function User(login) {
  this.login = login;
  this.sayHi = function(){
    console.log(this.login);
  }
}
var user = new User(&#39;John&#39;);
setTimeout(user.sayHi, 1000);
Nach dem Login kopieren

Der obige Code wird nur undefiniert angezeigt, da user.sayHi bei der Ausführung im globalen Objekt ausgeführt wird, sodass this.login den Wert nicht abrufen kann.

Um dieses Problem zu verhindern, besteht eine Lösung darin, user.sayHi in einer Funktion auszuführen.

setTimeout(function() {
  user.sayHi();
}, 1000);
Nach dem Login kopieren

Im obigen Code wird sayHi im Benutzerbereich und nicht im globalen Bereich ausgeführt, sodass der richtige Wert angezeigt werden kann.

Eine andere Lösung besteht darin, die Bindungsmethode zu verwenden, um sayHi an den Benutzer zu binden.

setTimeout(user.sayHi.bind(user), 1000);
Nach dem Login kopieren

HTML 5-Standard schreibt vor, dass das minimale Zeitintervall für setTimeout 4 Millisekunden beträgt. Um Strom zu sparen, erweitert der Browser das Zeitintervall für Seiten, die sich nicht im aktuellen Fenster befinden, auf 1000 Millisekunden. Wenn der Laptop außerdem im Akkubetrieb läuft, schalten Chrome und IE 9 und höher das Zeitintervall auf den System-Timer um, der etwa 15,6 Millisekunden beträgt.

2, setInterval()

Die Verwendung der Funktion setInterval ist genau die gleiche wie die von setTimeout. Der einzige Unterschied besteht darin, dass setInterval angibt, dass eine bestimmte Aufgabe einmal im Jahr ausgeführt werden soll while, was bedeutet, dass es sich nicht um eine unendliche Anzahl geplanter Ausführungen handelt.

<input type="button" onclick="clearInterval(timer)"value="stop">
<script>
  var i = 1  
var timer = setInterval(function(){
    console.log(2);
  }, 1000);
</script>
Nach dem Login kopieren

Der obige Code bedeutet, dass alle 1000 Millisekunden eine 2 ausgegeben wird, bis der Benutzer auf die Stopp-Schaltfläche klickt.

Wie setTimeout kann die setInterval-Methode zusätzlich zu den ersten beiden Parametern auch weitere Parameter akzeptieren, die an die Callback-Funktion übergeben werden. Hier ist ein Beispiel.

function f(){
  for (var i=0;i<arguments.length;i++){
    console.log(arguments[i]);
  }
}
setInterval(f, 1000, "Hello World");
Nach dem Login kopieren

Wenn sich die Webseite nicht im aktuellen Fenster (oder Tab) des Browsers befindet, beschränken viele Browser die durch setInteral angegebenen wiederkehrenden Aufgaben auf die Ausführung auf höchstens einmal pro Sekunde.

Das Folgende ist ein Beispiel für eine Webseitenanimation mit der setInterval-Methode.

var p = document.getElementById(&#39;somep&#39;);
var opacity = 1;
var fader = setInterval(function() 
{  opacity -= 0.1;
  if (opacity >= 0) {
    p.style.opacity = opacity;
  } else {
    clearInterval(fader);
  }}, 100);
Nach dem Login kopieren

Der obige Code legt die Transparenz des p-Elements alle 100 Millisekunden fest, bis es vollständig transparent ist.

SetInterval wird häufig zum Implementieren von Abfragen verwendet. Im Folgenden finden Sie ein Beispiel für die Abfrage, ob sich der Hashwert der URL geändert hat.

var hash = window.location.hash;
var hashWatcher = setInterval(function() {
  if (window.location.hash != hash) {
    updatePage(); 
 }}, 1000);
Nach dem Login kopieren

setInterval gibt das Intervall zwischen „Startausführung“ an und berücksichtigt nicht die Zeit, die von jeder Aufgabenausführung selbst verbraucht wird. In Wirklichkeit wird das Intervall zwischen den Ausführungen also kürzer sein als die angegebene Zeit. setInterval gibt beispielsweise die Ausführung alle 100 ms an und jede Ausführung dauert 5 ms. Dann beginnt die zweite Ausführung 95 Millisekunden nach dem Ende der ersten Ausführung. Wenn eine Ausführung besonders lange dauert, beispielsweise 105 Millisekunden, beginnt die nächste Ausführung unmittelbar nach deren Ende.

为了确保两次执行之间有固定的间隔,可以不用setInterval,而是每次执行结束后,使用setTimeout指定下一次执行的具体时间。

var i = 1;
var timer = setTimeout(function() {
  alert(i++);
  timer = setTimeout(arguments.callee,2000);
}, 2000);
Nach dem Login kopieren

上面代码可以确保,下一个对话框总是在关闭上一个对话框之后2000毫秒弹出。

根据这种思路,可以自己部署一个函数,实现间隔时间确定的setInterval的效果。

function interval(func, wait){
  var interv = function(){
    func.call(null);
    setTimeout(interv,wait);
  };
  setTimeout(interv,wait);
}interval(function(){
  console.log(2);
},1000);
Nach dem Login kopieren

上面代码部署了一个interval函数,用循环调用setTimeout模拟了setInterval。

HTML5标准规定,setInterval的最短间隔时间是10毫秒,也就是说,小于10毫秒的时间间隔会被调整到10毫秒。

3,clearTimeOut(),clearInterval()

setTimeout和setInterval函数,都返回一个表示计数器编号的整数值,将该整数传入clearTimeout和clearInterval函数,就可以取消对应的定时器。

var id1 = setTimeout(f,1000);
var id2 = setInterval(f,1000);
clearTimeout(id1);
clearInterval(id2);
Nach dem Login kopieren

setTimeout和setInterval返回的整数值是连续的,也就是说,第二个setTimeout方法返回的整数值,将比第一个的整数值大1。利用这一点,可以写一个函数,取消当前所有的setTimeout。

(function() {
  var gid = setInterval(clearAllTimeouts,0);
  function clearAllTimeouts(){
    var id = setTimeout(function(){}, 0);
    while (id >0) {
      if (id !==gid) {
        clearTimeout(id);
      }
      id--;
    }
  }})();
Nach dem Login kopieren

运行上面代码后,实际上再设置任何setTimeout都无效了。

下面是一个clearTimeout实际应用的例子。有些网站会实时将用户在文本框的输入,通过Ajax方法传回服务器,jQuery的写法如下。

$(&#39;textarea&#39;).on(&#39;keydown&#39;, ajaxAction);
Nach dem Login kopieren

这样写有一个很大的缺点,就是如果用户连续击键,就会连续触发keydown事件,造成大量的Ajax通信。这是不必要的,而且很可能会发生性能问题。正确的做法应该是,设置一个门槛值,表示两次Ajax通信的最小间隔时间。如果在设定的时间内,发生新的keydown事件,则不触发Ajax通信,并且重新开始计时。如果过了指定时间,没有发生新的keydown事件,将进行Ajax通信将数据发送出去。

这种做法叫做debounce(防抖动)方法,用来返回一个新函数。只有当两次触发之间的时间间隔大于事先设定的值,这个新函数才会运行实际的任务。假定两次Ajax通信的间隔不小于2500毫秒,上面的代码可以改写成下面这样。

$(&#39;textarea&#39;).on(&#39;keydown&#39;, debounce(ajaxAction, 2500))
Nach dem Login kopieren

利用setTimeout和clearTimeout,可以实现debounce方法,该方法用于防止某个函数在短时间内被密集调用。具体来说,debounce方法返回一个新版的该函数,这个新版函数调用后,只有在指定时间内没有新的调用,才会执行,否则就重新计时。

function debounce(fn, delay){
  var timer = null;// 声明计时器
  return function(){
    var context =this;
    var args = arguments;
    clearTimeout(timer); 
   timer = setTimeout(function(){
      fn.apply(context,args); 
   }, delay);
  };
}
Nach dem Login kopieren

// 用法示例

var todoChanges = _.debounce(batchLog, 1000);
Object.observe(models.todo, todoChanges);
Nach dem Login kopieren

现实中,最好不要设置太多个setTimeout和setInterval,它们耗费CPU。比较理想的做法是,将要推迟执行的代码都放在一个函数里,然后只对这个函数使用setTimeout或setInterval。

4,运行机制

setTimeout和setInterval的运行机制是,将指定的代码移出本次执行,等到下一轮EventLoop时,再检查是否到了指定时间。如果到了,就执行对应的代码;如果不到,就等到再下一轮Event Loop时重新判断。

这意味着,setTimeout和setInterval指定的代码,必须等到本轮EventLoop的所有同步任务都执行完,再等到本轮EventLoop的“任务队列”的所有任务执行完,才会开始执行。由于前面的任务到底需要多少时间执行完,是不确定的,所以没有办法保证,setTimeout和setInterval指定的任务,一定会按照预定时间执行。

setTimeout(someTask, 100);
veryLongTask();
Nach dem Login kopieren

上面代码的setTimeout,指定100毫秒以后运行一个任务。但是,如果后面的veryLongTask函数(同步任务)运行时间非常长,过了100毫秒还无法结束,那么被推迟运行的someTask就只有等着,等到veryLongTask运行结束,才轮到它执行。

这一点对于setInterval影响尤其大。

setInterval(function () {
  console.log(2);
}, 1000);
(function () {
  sleeping(3000);
})();
Nach dem Login kopieren

上面的第一行语句要求每隔1000毫秒,就输出一个2。但是,第二行语句需要3000毫秒才能完成,请问会发生什么结果?

结果就是等到第二行语句运行完成以后,立刻连续输出三个2,然后开始每隔1000毫秒,输出一个2。也就是说,setIntervel具有累积效应,如果某个操作特别耗时,超过了setInterval的时间间隔,排在后面的操作会被累积起来,然后在很短的时间内连续触发,这可能或造成性能问题(比如集中发出Ajax请求)。

5, setTimeout(f,0)

setTimeout的作用是将代码推迟到指定时间执行,如果指定时间为0,即setTimeout(f, 0),那么会立刻执行吗?

答案是不会。因为上一段说过,必须要等到当前脚本的同步任务和“任务队列”中已有的事件,全部处理完以后,才会执行setTimeout指定的任务。也就是说,setTimeout的真正作用是,在“消息队列”的现有消息的后面再添加一个消息,规定在指定时间执行某段代码。setTimeout添加的事件,会在下一次Event Loop执行。

setTimeout(f, 0)将第二个参数设为0,作用是让f在现有的任务(脚本的同步任务和“消息队列”指定的任务)一结束就立刻执行。也就是说,setTimeout(f, 0)的作用是,尽可能早地执行指定的任务。而并不是会立刻就执行这个任务。

setTimeout(function () {
  console.log(&#39;hello world!&#39;);
}, 0);
Nach dem Login kopieren

上面代码的含义是,尽可能早地显示“hello world!”。

setTimeout(f, 0)指定的任务,最早也要到下一次EventLoop才会执行。请看下面的例子。

setTimeout(function() {
  console.log("Timeout");
}, 0)
function a(x) {
  console.log("a()开始运行");
  b(x);
  console.log("a()结束运行");
}
function b(y) {
  console.log("b()开始运行");
  console.log("传入的值为" + y);
  console.log("b()结束运行");
}
console.log("当前任务开始");
a(42);
console.log("当前任务结束");
Nach dem Login kopieren

输出结果如下:

// 当前任务开始, a() 开始运行, b() 开始运行, 传入的值为42,b() 结束运行, a() 结束运行, 当前任务结束

上面代码说明,setTimeout(f, 0)必须要等到当前脚本的所有同步任务结束后才会执行。

即使消息队列是空的,0毫秒实际上也是达不到的。根据HTML5标准,setTimeout推迟执行的时间,最少是4毫秒。如果小于这个值,会被自动增加到4。这是为了防止多个setTimeout(f, 0)语句连续执行,造成性能问题。

另一方面,浏览器内部使用32位带符号的整数,来储存推迟执行的时间。这意味着setTimeout最多只能推迟执行2147483647毫秒(24.8天),超过这个时间会发生溢出,导致回调函数将在当前任务队列结束后立即执行,即等同于setTimeout(f, 0)的效果。

6 ,正常任务与微任务

正常情况下,JavaScript的任务是同步执行的,即执行完前一个任务,然后执行后一个任务。只有遇到异步任务的情况下,执行顺序才会改变。

这时,需要区分两种任务:正常任务(task)与微任务(microtask)。它们的区别在于,“正常任务”在下一轮EventLoop执行,“微任务”在本轮Event Loop的所有任务结束后执行。

console.log(1);
setTimeout(function() {
  console.log(2);
}, 0);
Promise.resolve().then(function() {
  console.log(3);
}).then(function() {
  console.log(4);
});
console.log(5);
Nach dem Login kopieren

输出结果如下:

// 1, 5,3,4, 2

上面代码的执行结果说明,setTimeout(fn, 0)在Promise.resolve之后执行。

这是因为setTimeout语句指定的是“正常任务”,即不会在当前的Event Loop执行。而Promise会将它的回调函数,在状态改变后的那一轮Event Loop指定为微任务。所以,3和4输出在5之后、2之前。

正常任务包括以下情况。

•   setTimeout

•   setInterval

•   setImmediate

•   I/O

•   各种事件(比如鼠标单击事件)的回调函数

微任务目前主要是process.nextTick和 Promise 这两种情况。

相关推荐:


 

Das obige ist der detaillierte Inhalt vonEinführung in die Verwendung von Timer-Funktionen in js (mit Code). Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Verwandte Etiketten:
Quelle:php.cn
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage