almost 3 years ago

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) {};
輸出結果:
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 QuenuCall Stack可至該篇看Event Driven的觀念。
Javascript Event Driven


setTimeout非同步的範例

首先看看下面的程式碼,doSomething函數需要等到取得到data才執行,但getData會執行很久,但下面的doSomething12不需要data就可以執行,所以這時這種寫法就會很浪費時間。

var data = getData();
doSomething(data);

doSomething1();
doSomething2();

所以我們將getDatafucntion修改為如下。

function getData(callBack){         
    setTimeout(function(){
        //getData要執行的程式碼

        callBack();
    },10);
}

然後我們整段程式碼就可以改成。

getData(doSomething);
doSomething1();
doSomething2();

上面這種寫法,我們把同步操作轉變成非同步操作,getData不會阻塞住整個線程,以上就是其種一種的非同步的寫法,但這種寫法有個缺點就是很容易變成CallBack地獄。


參考資料

← Javascript之Event Driven Javascript非同步編程的方法(Pub/Sub) →
 
comments powered by Disqus