1. 程式人生 > >js實現偽非同步操作

js實現偽非同步操作

瀏覽器中的JS執行緒和UI執行緒以列隊的形式同步執行的,原因是s是可操縱DOM的,如果在修改這些元素屬性同時渲染介面(即JS執行緒和UI執行緒同時執行),那麼渲染執行緒前後獲得的元素資料就可能不一致了。因此為了防止渲染出現不可預期的結果,這裡所謂的偽非同步,是指在執行js程式碼的同時能達到UI渲染的效果。

例如我們點選一個按鈕然後js有一段很複雜的計算,我們希望在計算的過程中能夠有一個正在執行的動畫來提高使用者體驗,我們以下面的程式碼來寫的時候,其實是不可行的。

//顯示載入動畫
utils.loading();
//耗時操作
for(var i=0;i<100;i++){
	console.log(11);
}
//關閉載入動畫
utils.closeload();
原因就是上面說的js執行緒和UI執行緒是同步執行的,在js引擎執行指令碼期間,瀏覽器渲染執行緒都是處於掛起狀態的,也就是說被”凍結”了,而我們可以用setTimeout方法來實習偽非同步,因為setTimeout執行時會新開一個定時器執行緒,這是正好處於JS執行緒運行當中,當JS執行緒執行完成後,發現setTimeout馬上就要開始執行(即時間小於上述的臨界值),為了避免UI執行緒執行時間太長而帶來的setTimeout嚴重拖時的不好體驗,瀏覽器選擇一直等待直到setTimeout到期,然後執行裡面的js。如果發現setTimeout還要隔較長時間才到期,為了避免時間上的浪費,瀏覽器選擇馬上切換到UI執行緒。因此設定setTimeout大一點(大於100ms便可)時,便會有時間切換成UI執行緒進行UI渲染,類似如下程式碼。
//顯示載入動畫
utils.loading();
//讓JS執行緒等待100毫秒,等待會讓UI渲染程序實現,
//如果發現setTimeout還要隔較長時間才到期,為了避免時間上的浪費,瀏覽器選擇馬上切換到UI執行緒。 
setTimeout(function(){
	//長時間的js計算,同步請求等耗時操作
	for(var i=0;i<100;i++){
		console.log(11);
	}
	//關閉載入動畫
	utils.closeload();
},1000);