Promise 解決了回調地獄,在處理一些需要花費比較長時間的任務時使用 Promise 就可以進行非同步的處理,防止阻塞。
使用方式:
利用 Constructor 製作一個 Promise 物件,且 Promise 會接收一個 function 作為參數,傳遞給 Promise 的 function 有 resolve 和 reject 參數,resolve 表示成功,reject 表示失敗。
// Initialize a promise
const promise = new Promise((resolve, reject) => {})
console.log(promise);
這時候開啟 Devtool 可以看到 PromiseState 為 pending(進行中),表示 resolve 或 reject 之前的初始狀態,因為我們還沒設定 resolve 和 reject 要做啥事。
PromiseState 分為三種:
- pending - 進行中
- fulfilled- 操作成功,promise 已解決
- rejected - 操作失敗,promise 被拒絕
將 Promise 展開,可以看到裡面有 Promise()
, catch()
, then()
, finally()
。
then()
表示處理 resolvecatch()
表示處理 rejectfinally()
當一個 promise 被解決時調用,無論結果是成功或是失敗都會執行。接著再將 Promise() 這個 constructor 展開,可以發現裡面有許多方法,包含了 resolve()
,reject()
,race()
,all()
...等。
Promise.resolve()
作用為將 PromiseState 由 pending 變成 fulfilledPromise.reject()
作用為將 PromiseState 由 pending 變成 rejectedPromise.race()
用於處理多個 Promise,只要有一個成功,就 return 成功結果,其他的被淘汰,如果全部失敗,就 return 失敗Promise.all()
用於處理多個 Promise,如果有其中一個 Promise 失敗全部就失敗,而全部的 Promise 都成功才代表成功。來舉個簡單的例子~
function fn1(){
setTimeout(function(){
console.log(1)
},0)
}
function fn2(){
console.log(2)
}
fn1()
fn2()
// 2
// 1
setTimeout() 為非同步事件,即使時間設定 0 秒,JavaScript 也會先跳過它,先往下執行別的動作,最後再回來執行它,所以最終的結果會先印出 2 再印出 setTimeout() 裡的 1。
如果我們想要結果如同執行 function 的順序,先印出 fn1() 再印出 fn2(),可以使用 Promise()。
function fn1() {
return new Promise((resolve, reject) => {
setTimeout(function () {
console.log(1);
resolve(); // 這個 resolve 會決定 fn 什麼時候會進 then
}, 0)
})
}
function fn2() {
console.log(2);
}
fn1().then(fn2); // 執行後 console.log 的順序為 1 => 2
// 1
// 2
再來舉個不只一個 Promise 的例子:
const PROMISE1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("PROMISE1");
},0)
})
const PROMISE2 = new Promise((resolve, reject) => {
setTimeout(() => {
reject("PROMISE2");
},1000)
})
const RES = Promise.race([PROMISE1,PROMISE2]);
console.log(RES)
上面的例子使用 race(),只要有一個成功最終的結果就是成功,而因為 PROMISE1 執行時就 resolve,所以最後 PromiseState 會顯示 fulfilled。
將上面的程式碼改一下
const PROMISE1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("PROMISE1");
},2000)
})
const PROMISE2 = new Promise((resolve, reject) => {
setTimeout(() => {
reject("PROMISE2");
},1000)
})
const RES = Promise.race([PROMISE1,PROMISE2]);
console.log(RES)
因為 PROMISE2 設定的時間比 PROMISE1 短,會先執行 PROMISE2,而 PROMISE2 裡面是 reject,所以最後 PromiseState 會顯示 rejected,且 PromiseResult 為 PROMISE2。
參考資料:
Promise - MDN
Understanding the Event Loop, Callbacks, Promises, and Async/Await in JavaScript
最後推薦一下不錯的資源: