Heim > Web-Frontend > js-Tutorial > Hauptteil

setTimeout-Geheimnisse, die JavaScript-Entwickler kennen sollten

黄舟
Freigeben: 2017-02-20 14:22:04
Original
1194 Leute haben es durchsucht

Timer

setTimeout
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

ist etwas, das wir häufig verwenden. Es wird verwendet, um eine Funktion aufzurufen oder einen Ausdruck nach einer bestimmten Anzahl von Millisekunden zu berechnen.

Syntax:

setTimeout(code, millisec, args);
Nach dem Login kopieren



Hinweis: Wenn der Code eine Zeichenfolge ist, entspricht dies dem Ausführen der auszuführenden Methode

eval()
Nach dem Login kopieren

der Code.

Natürlich erfahren Sie in diesem Artikel nicht nur, wie Sie

setTimeout
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

verwenden, sondern auch, wie es ausgeführt wird.

1. Prinzip von setTimeout

Sehen wir uns zunächst einen Code an:

var start = new Date(); 
var end = 0; 
setTimeout(function() {  console.log(new Date() - start); }, 500); 
while (new Date() - start <= 1000) {}
Nach dem Login kopieren

Oben Code, definieren Ein

setTimeout
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Timer wird erstellt und die Verzögerungszeit beträgt 500 Millisekunden.

Glauben Sie, dass das Druckergebnis 500 ist?

Aber Tatsache ist, dass es Ihre Erwartungen übertrifft. Das Druckergebnis ist so (vielleicht wird es anders sein, wenn Sie es ausdrucken). aber es wird definitiv größer als 1000 Millisekunden sein):

setTimeout-Geheimnisse, die JavaScript-Entwickler kennen sollten

Warum ist das so? Der Grund dafür ist, dass JavaScript in einem einzelnen Thread ausgeführt wird. Mit anderen Worten: Zu jedem Zeitpunkt gibt es nur einen Thread, der das JavaScript-Programm ausführt, und es können nicht mehrere Codeteile gleichzeitig ausgeführt werden.

Werfen wir einen Blick auf JavaScript im Browser.

Der Kernel des Browsers arbeitet unter der Kontrolle des Kernels zusammen, um die Synchronisierung aufrechtzuerhalten. Ein Browser implementiert mindestens drei residente Threads: JavaScript-Engine-Thread, GUI-Rendering-Thread und Browser Ereignis auslösender Thread.

JavaScript引擎
Nach dem Login kopieren

basiert auf der ereignisgesteuerten Single-Thread-Ausführung. Die JavaScript-Engine wartet immer auf das Eintreffen von Aufgaben in der Aufgabenwarteschlange und verarbeitet diese dann nur Es kann jederzeit ein JavaScript-Thread ausgeführt werden.

GUI渲染线程
Nach dem Login kopieren

ist für das Rendern der Browseroberfläche verantwortlich (Repaint) oder ein Reflow (Reflow) wird durch einen Vorgang verursacht . Es ist jedoch zu beachten, dass sich der GUI-Rendering-Thread und die JavaScript-Engine gegenseitig ausschließen. Wenn die JavaScript-Engine ausgeführt wird, wird der GUI-Thread angehalten und GUI-Updates werden in einer Warteschlange gespeichert und sofort ausgeführt, wenn die JavaScript-Engine ausgeführt wird Motor ist im Leerlauf.

事件触发线程
Nach dem Login kopieren

: Wenn ein Ereignis ausgelöst wird, fügt der Thread das Ereignis am Ende der ausstehenden Warteschlange hinzu und wartet auf die Verarbeitung durch die JavaScript-Engine. Diese Ereignisse können aus dem Codeblock stammen, der derzeit von der JavaScript-Engine ausgeführt wird, z. B. setTimeout, oder von anderen Threads im Browserkernel, z. B. Mausklicks, asynchronen Ajax-Anforderungen usw. Dies liegt jedoch an der Single-Thread-Beziehung von JavaScript , alle diese Ereignisse müssen in die Warteschlange gestellt und auf die Verarbeitung durch die JavaScript-Engine gewartet werden (Asynchroner Code wird nur ausgeführt, wenn kein synchroner Code im Thread ausgeführt wird).

Sehen wir uns hier noch einmal das ursprüngliche Beispiel an:

var start = new Date();
 var end = 0;
 setTimeout(function() {  console.log(new Date() - start); }, 500);
 while (new Date() - start <= 1000) {}
Nach dem Login kopieren

Obwohl die Verzögerungszeit von

setTimeout
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

500 Millisekunden beträgt , aber aufgrund der Existenz der

while
Nach dem Login kopieren

-Schleife springt die while-Schleife nur dann heraus, wenn das Intervall größer als 1000 Millisekunden ist. Das heißt, vor 1000 Millisekunden belegt die while-Schleife die JavaScript-Thread. Mit anderen Worten: Erst nachdem der Thread darauf gewartet hat, aus while herauszuspringen, wird er in den Leerlauf versetzt und führt den zuvor definierten setTimeout aus.

Abschließend können wir daraus schließen, dass

setTimeout
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

nur garantieren kann, dass die Aufgabe (Funktion, die ausgeführt werden muss) in die Aufgabenwarteschlange eingefügt wird, um nach der angegebenen Zeit zu warten, aber Es gibt keine Garantie dafür, dass diese Aufgabe ausgeführt wird. Sobald der Thread, der das Javascript ausführt, frei ist, entfernen Sie die Aufgabe aus der Warteschlange und führen Sie sie aus.

Da der JavaScript-Thread nicht durch zeitaufwändige Vorgänge blockiert wird, kann er die Aufgaben in der Warteschlange schnell herausnehmen und ausführen. Es ist auch dieser Warteschlangenmechanismus, der für uns die Illusion einer asynchronen Ausführung erzeugt .

2. Ein guter Partner von setTimeout „0“

Vielleicht haben Sie den folgenden Code gesehen:

setTimeout(function(){ // statement}, 0);
Nach dem Login kopieren


Der obige Code bedeutet sofortige Ausführung. Die ursprüngliche Absicht besteht darin, die aufrufende Funktion sofort auszuführen, aber tatsächlich wird der obige Code nicht sofort ausgeführt. Dies liegt daran, dass setTimeout eine minimale Ausführungszeit hat. Wenn die angegebene Zeit kürzer als diese Zeit ist, verwendet der Browser die minimal zulässige Zeit time als setTimeout. Das heißt, selbst wenn wir die Verzögerungszeit von setTimeout auf 0 setzen, startet das aufgerufene Programm nicht sofort.

Die tatsächliche Situation verschiedener Browser ist unterschiedlich. Die Zeitgenauigkeit von IE8 und früheren IE beträgt 15,6 ms. Mit dem Aufkommen von HTML5 beträgt das definierte Mindestzeitintervall jedoch nicht weniger als 4 Millisekunden. Wenn es unter diesem Wert liegt, wird es automatisch erhöht, und zwar im Jahr 2010 und später konsistent in allen veröffentlichten Browsern übernommen.

Wenn wir also

setTimeout(fn,0)
Nach dem Login kopieren
Nach dem Login kopieren

schreiben, implementieren wir tatsächlich die Warteschlangensprungoperation, bei der der Browser „so schnell wie möglich“ zurückrufen muss, aber das ist tatsächlich möglich Bald kommt es auf den Browser an.

Dann

setTimeout(fn, 0)
Nach dem Login kopieren

Was nützt es? Tatsächlich liegt der Nutzen darin, dass wir die Reihenfolge der Aufgabenausführung ändern können! Weil der Browser die in der setTimeout-Warteschlange angesammelten Aufgaben ausführt, nachdem er die Aufgaben in der aktuellen Aufgabenwarteschlange abgeschlossen hat.

Indem Sie die nach der Verzögerung auszuführende Aufgabe auf 0s setzen, können Sie die Reihenfolge der Aufgabenausführung ändern, das Auftreten der Aufgabe verzögern und sie asynchron ausführen lassen.

Schauen wir uns ein beliebtes Beispiel im Internet an:

document.querySelector(&#39;#one input&#39;).onkeydown = function() {  
     document.querySelector(&#39;#one span&#39;).innerHTML = this.value;
 }; 
document.querySelector(&#39;#second input&#39;).onkeydown = function() {    
     setTimeout(function() {  
         document.querySelector(&#39;#second span&#39;).innerHTML = document.querySelector(&#39;#second input&#39;).value; }, 0);
};
Nach dem Login kopieren

`实例:实例

当你往两个表单输入内容时,你会发现未使用setTimeout函数的只会获取到输入前的内容,而使用setTimeout函数的则会获取到输入的内容。

这是为什么呢?

因为当按下按键的时候,JavaScript 引擎需要执行 keydown 的事件处理程序,然后更新文本框的 value 值,这两个任务也需要按顺序来,事件处理程序执行时,更新 value值(是在keypress后)的任务则进入队列等待,所以我们在 keydown 的事件处理程序里是无法得到更新后的value的,而利用 setTimeout(fn, 0),我们把取 value 的操作放入队列,放在更新 value 值以后,这样便可获取出文本框的值。

未使用setTimeout函数,执行顺序是:`onkeydown => onkeypress => onkeyup

使用setTimeout函数,执行顺序是:
Nach dem Login kopieren

onkeydown => onkeypress => function => onkeyup`

虽然我们可以使用

keyup
Nach dem Login kopieren
Nach dem Login kopieren

来替代

keydown
Nach dem Login kopieren

,不过有一些问题,那就是长按时,

keyup
Nach dem Login kopieren
Nach dem Login kopieren

并不会触发。

长按时,keydown、keypress、keyup的调用顺序:

keydown
keypress
keydown
keypress
...
keyup
Nach dem Login kopieren

也就是说keyup只会触发一次,所以你无法用keyup来实时获取值。

我们还可以用

setImmediate()
Nach dem Login kopieren

来替代

setTimeout(fn,0)
Nach dem Login kopieren
Nach dem Login kopieren



if (!window.setImmediate) {  
    window.setImmediate = function(func, args){  
      return window.setTimeout(func, 0, args);  
   };  
  window.clearImmediate = window.clearTimeout;
 }
Nach dem Login kopieren

setImmediate()`方法用来把一些需要长时间运行的操作放在一个回调函数里,在浏览器完成后面的其他语句后,就立刻执行这个回调函数,必选的第一个参数func,表示将要执行的回调函数,它并不需要时间参数。

注意:目前只有IE10支持此方法,当然,在Nodejs中也可以调用此方法。

3、setTimeout的一些秘密

3.1 setTimeout中回调函数的this

由于setTimeout() 方法是浏览器 window 对象提供的,因此第一个参数函数中的this其实是指向window对象,这跟变量的作用域有关。

看个例子:

var a = 1; 
var obj = {  
a: 2, 
 test: function() {  setTimeout(function(){  console.log(this.a);  }, 0);  
} 
}; 
obj.test(); // 1
Nach dem Login kopieren

不过我们可以通过使用bind()方法来改变setTimeout回调函数里的this

var a = 1; 
var obj = { 
 a: 2, 
 test: function() {  
setTimeout(function(){  
console.log(this.a);  
}.bind(this), 0);  
}
 }; 
obj.test(); // 2
Nach dem Login kopieren

3.2 setTimeout不止两个参数

我们都知道,setTimeout的第一个参数是要执行的回调函数,第二个参数是延迟时间(如果省略,会由浏览器自动设置。在IE,FireFox中,第一次配可能给个很大的数字,100ms上下,往后会缩小到最小时间间隔,Safari,chrome,opera则多为10ms上下。)

其实,setTimeout可以传入第三个参数、第四个参数….,它们表示神马呢?其实是用来表示第一个参数(回调函数)传入的参数。

setTimeout(function(a, b){  
console.log(a); // 3 
console.log(b); // 4},0, 3, 4);
Nach dem Login kopieren


 以上就是JavaScript 开发者应该知道的 setTimeout 秘密 的内容,更多相关内容请关注PHP中文网(www.php.cn)!

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
Über uns Haftungsausschluss Sitemap
Chinesische PHP-Website:Online-PHP-Schulung für das Gemeinwohl,Helfen Sie PHP-Lernenden, sich schnell weiterzuentwickeln!