0%

JS核心-函式-Promise物件

上一篇,介紹了js中的函式與非同步環境會造成的callback Hell的前因後果,最終需要Promise來解決這個問題的過程後,此篇要記錄怎麼使用Promise物件。

Promise物件

Promise物件包含兩個東西,一個叫reslove 另一個叫reject
當該Promise執行成功的話,就會去呼叫reslove,失敗的話,就會去執行reject的內容。

Promise物件創建的方法

書中有提供兩種,其實意思差不多
函式運算式用new來創建

1
2
3
4
const FirstPromise = new Promise((resolve, reject) => {
resolve(某個資料);
reject('Promise failure');
})

函式回傳new Promise物件

1
2
3
4
5
6
function FirstPromise() {
return new Promise((resolve, reject) => {
resolve(某個資料);
reject('Promise failure');
})
}

then - 解決同步問題,依序執行函式

以上這個範例,可以看到我們利用創三個Promise物件,並利用then,來依序執行這三個非同步的函式內容。

Promise.all 和 Promise.race - 解決非同步問題

若今天我們不在乎函式們的執行順序,只在乎他們有沒有執行完畢的話我們就可以使用 Promise.all 或 Promise.race。
Promise.all 和 Promise.race相異之處
Promise.all: 會等到所有的函式都執行完resolve之後,才會去執行then的內容。
Promise.race: 只要其中一個函式執行完它的resolve後,就會去執行then的內容,但是,其他還沒執行完的函式並不會被取消,也是一樣會被執行喔。

Promise.all 和 Promise.race相同之處
只要有其中一個函式回傳reject的話,就會中止執行其他的函式。

Promise.all範例

Promise.race範例

async/await - 讓Promise寫法更簡潔

這個寫法是可以讓Promise寫法更簡潔。
代替then寫法
我們想要依序處理非同步函式,之前我們是用then來達成,那這邊我們使用async/await來達成。
step1.
先創建一些Promise物件
step2.
創一個async function並在這個函式裡面,使用await來呼叫在step1創建的Promise物件,最後,程式就會依照await呼叫的順序,
來依序執行這些Promise物件,達到跟then一樣的效果囉。

以上這個範例,就可以看出來我們利用async/await 來控制這些非同步函式的執行順序囉。

用在Promise.all

可以看到,Done的內容,會在Promise.all裡面的函式都resolve後,才出現。

setTimeout 與 setInterval的使用

setTimeout
這個功能是延遲一段時間之後,只執行一次該function內的內容。
setInterval
這個功能是延遲一段時固定間之後,執行該function內的內容,並循環這樣的操作。

clearTimeout(timeID) 與 clearInterval(timeID)

它們倆個都會回傳一個timerID,那我們就可以透過這些timerID來將這些相對應的setTimeout和setInterval的功能取消掉。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
let timerID = window.setTimeout(function(){
console.log('first one');
}, 2000);

let timerID1 = window.setTimeout(function(){
console.log('second one');
}, 1000);

let timerID2 = window.setInterval(function(){
console.log('third one');
}, 1000);
console.log(timerID, timerID1, timerID2)
window.clearTimeout(timerID); // 將timerID取消掉
window.clearInterval(timerID2); // 將timerID2取消掉

但是,要特別注意一下,clearTimeout要在你設定的Timeout時機以內取消掉他才有用喔,不然等它執行之後才取消的話,clearTimeout就沒啥用。

JS單執行緒 與 同步、非同步之間的關係

JavaScript是「單執行緒」的語言,就代表它同一時間只能做一項任務。
那這樣的話,怎麼還會有同步和非同步的概念的出現呢?
這是因為,JS的設計者把要執行的任務分成同步和非同步的任務。
setTimeoutajax(將口罩地圖的api接近來的行為)這些功能,就是非同步的任務。

這邊要再複習一下,Promise物件是主要用來控制非同步的任務的作用順序。

主執行緒 和 Event Queue

JS一開始會把所有任務,不管它是同步還是非同步都會先把它們都放在主執行緒裡面排序好,當程式開始執行主行緒裡面的任務時,
當它一遇到非同步的任務,就會跳過不執行,並將該非同步任務放到Event Queue裡面。
等到主行緒裡面的任務都執行完畢之後,才接著繼續執行Event Queue裡面的callback function。

執行緒的操作過程

以上這個範例你可以看到,就算我們將setTimeout的延遲時間設定為0秒,但最終,還是最後才執行它的內容,由此可以看出來他是被放在event queue裡面,最後才被執行。

js主執行緒機制會導致非同步函式延遲

那因為js有以上這種會將非同步函式放在event queue的特性,當主執行緒的執行任務太多,執行時間太久的話,可能會延遲非同步函式的執行時間,進而導致像是setTimeout和setInterval所設定的時間不準。