在Javascript單線程
與Javascript之Event Driven
這兩篇文章中,我們大概了解了單線程與非同步事件的工作原理,在這篇中我們將會說明運用SetTimeout來處理非同步事件。
setTimeout基本用法
SetTimeout為Javascript的原生函數,主要的用法為在一個指定的延遲時間後執行某個函數
。
下列程式碼為setTimeout的基本使用,代表在1秒鐘後執行console.log(“Hello”)。
setTimeout(function(){
console.log("Hello")
},1000);
這邊要注意一點,雖然上面程式碼是設定1秒,但是Javascript為單線程,因此如過將程式碼修改如下,讓單線程被While
阻塞,setTimeout
就不會在1秒後執行,而是等while執行完在執行。
var start = new Date;
setTimeout(function(){
var end = new Date;
console.log('Time elapsed:', end - start, 'ms');
}, 1000);
while (new Date - start < 2000) {};
<!-- tas -->
輸出結果:
Time elapsed: 2002 ms
---
setTimeout ( 0 ) 的意思
SetTimeout為在一個指定的延遲時間後執行某個函數
,所以如果帶入(0)
,則是否意味馬上執行的意思?來看下面程式碼。
setTimeout(function(){
console.log("Hello");
},0)
console.log("Mark");
執行結果為:
Mark
Hello
嚴來來說不是立即執行,而是立即排進Task Quenu
等待執行,等Call Stack
空時它會至Task Quenu
尋找工作,因此執行結果才為Mark Hello
。
如果不知道Task Quenu
或Call Stack
可至該篇看Event Driven
的觀念。
Javascript Event Driven
## setTimeout非同步的範例
首先看看下面的程式碼,doSomething
函數需要等到取得到data
才執行,但getData
會執行很久,但下面的doSomething1
與2
不需要data
就可以執行,所以這時這種寫法就會很浪費時間。
var data = getData();
doSomething(data);
doSomething1();
doSomething2();
所以我們將getData
fucntion修改為如下。
function getData(callBack){
setTimeout(function(){
//getData要執行的程式碼
callBack();
},10);
}
然後我們整段程式碼就可以改成。
getData(doSomething);
doSomething1();
doSomething2();
上面這種寫法,我們把同步操作轉變成非同步操作,getData不會阻塞住整個線程,以上就是其種一種的非同步的寫法,但這種寫法有個缺點就是很容易變成CallBack地獄。