Promise - 處理同步、非同步事件 - 1

callback hell

JavaScript 中有很多非同步的事件,例如:AJAX、setTimeout、各種 event 事件(click,onchange…)等,由於 JavaScript 為單執行緒的程式語言(參考這邊),這些事件我們很常使用 callback,在一層包一層後就會出現知名的 callback 地獄,而 ES6 開始新增了 Promise 物件就是為了解決此問題而生的。

Promise 的狀態與流程

Promise 承諾,顧名思義就是「保證達到某個條件之後才會再做什麼事情」。
Promise 物件會有以下這幾種狀態:

  • pending: 等待中的初始狀態
  • fulfilled: 正確完成
  • rejected: 已拒絕,操作失敗

剛進入 Promise 時,我們會進入 pending (等待事件完成)的狀態,接下來會依據事件的成功與否來回傳成功或拒絕的 callback,通常我們會使用 resolvereject 兩個變數來傳送成功與失敗的訊息(資料)。

1
2
3
4
let myFirstPromise = new Promise((resolve, reject) => {
resolve(someValue); // fulfilled
reject('failure reason'); // rejected
});

以下圖為範例,ASin 一開始在原地準備要跑步,此時他有兩種結果,一種是他正確的完成跑步這件事,最後他回報他跑了幾秒鐘;另一種結果是他拒絕跑步這件事,為什麼?他回報他就是不想跑步了。

Promise 流程圖
我們將這整個過程寫成 Promise 物件來進行,可得以下的原始碼,首先,我們利用建構式建立一個 Promise 物件,並將此物件賦予給 running 這個變數,在 Promise 物件中引用 resolvereject 變數來做 fulfilled 或 rejected 狀態時的訊息(資料)傳遞,在此我們寫了隨機產生是否要跑步及跑步秒數的變數,帶入我們的 if…else 陳述式,當 run 為 true (確定跑步,fulfilled)時,則調用 resolve() 來傳遞跑了幾秒鐘,若是 run 為 false,則調用 reject() 來傳遞不想跑了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
let running = new Promise((resolve, reject) => {
// 使用 resolve、reject 兩個變數來傳送訊息
let run = Math.floor(Math.random() * 2); // 隨機產生 0 或 1 同 false or true
let duration = Math.floor(Math.random() * 10) + 1; // 隨機產生 1 ~ 10
console.log('隨機是否要跑步:' + run, '預計跑步秒數:' + duration);
if (run) {
window.setTimeout(() => {
resolve('跑了' + duration + '秒');
}, duration * 1000);
} else {
reject('我不想跑了');
}
});
running
.then(data => {
console.log(data);
})
.catch(data => {
console.log(data);
});

最後,我們如何去執行這個物件來處理非同步與同步事件並接收訊息呢?
我們可以使用 then()catch()來接收,從範例中可以看到,當 Promise 中執行的條件有滿足時,我們在then()傳入一個 function 並使用 data 變數來接收 fulfilled 狀態所傳遞的訊息,同樣的 rejected 狀態則是使用catch()來接收。
Promise執行結果-fulfilled
Promise執行結果-rejected

0%