Javascript 非同步編程的方法 - setTimeout
javascript
Lastmod: 2019-12-13

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 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地獄。

參考資料

comments powered by Disqus