0%

JS 核心觀念筆記 - 建立一個 Promise

core

在開發者工具透過 console.log(Promise),會得到一個 Promise 的函式,如下方結果,但因為裡面沒有內容,所以不會有任何結果。

1
2
console.log(Promise)
ƒ Promise() { [native code] }

改用 console.dir(Promise),就可以看到 Promise 變成一個物件,並且有自己的方法,像是 rejectresolve,接收結果的 thencatch 也在裡面。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
console.dir(Promise)

ƒ Promise()
all: ƒ all()
allSettled: ƒ allSettled()
any: ƒ any()
arguments: (...)
caller: (...)
length: 1
name: "Promise"
prototype: Promise {Symbol(Symbol.toStringTag): "Promise", constructor: ƒ, then: ƒ, catch: ƒ, finally: ƒ}
race: ƒ race()
reject: ƒ reject()
resolve: ƒ resolve()
Symbol(Symbol.species): (...)
get Symbol(Symbol.species): ƒ [Symbol.species]()
__proto__: ƒ ()
[[Scopes]]: Scopes[0]

實體化 promise

既然 Promise 是一個物件,那也可以將其實體化,並使用它,下方就是實體化的起手式。

1
2
const a = new Promise(() => {});
console.log(a);

透過開發者工具可以看到下方資訊:

1
2
3
4
Promise {<pending>}
__proto__:Promise
[[PromiseState]]: "pending"
[[PromiseResult]]: undefined
  • Promise 正在 pending 未確認狀態。
  • 目前值的結果是 undefined,在透過 resolvereject 回傳後就會得結果的值。

resolve

所以會帶入剛剛提到的兩個參數,resolvereject,要注意的地方為一次只會執行一個,下方帶入 resolve 的方法,並且把要顯示的結果也寫入。

1
2
3
4
const a = new Promise((resolve, reject) => {
resolve("執行成功");
});
console.log(a);

在看到開發人員工具,會看到 Promise 的狀態也改變了。

1
2
3
4
Promise {<fulfilled>: "執行成功"}
__proto__: Promise
[[PromiseState]]: "fulfilled"
[[PromiseResult]]: "執行成功"

這時候知道是成功獲得資料,就可以使用 Promise 接收資料的方法來取得資料,所以可以用 then()。

1
2
3
a.then((res) => {
console.log(res); // 執行成功
});

reject

那失敗當然就是執行 reject 的方法。

1
2
3
4
const a = new Promise((resolve, reject) => {
reject("執行失敗");
});
console.log(a);

開發者工具就會得到:

1
2
3
4
Promise {<rejected>: "執行失敗"}
__proto__: Promise
[[PromiseState]]: "rejected"
[[PromiseResult]]: "執行失敗"

但是這地方會跳錯,因為之前還沒有寫上接收失敗結果的方法。

失敗就要使用 catch 來接收資料傳遞失敗的的結果,但不需要重新寫一個方法,而是直接在 then 的方法後面直接加上 catch 的方法即可。

1
2
3
4
5
a.then((res) => {
console.log(res);
}).catch((res) => {
console.log(res); // 執行失敗
});

以上為 Promise 建立時的基本概念,實務上並不會這樣寫。

通常如果要建立一個 Promise 的實體,會使用函式,不管用具名或是匿名函式都可以,以下為基本 Promise 完成後的程式碼。

1
2
3
4
5
6
7
8
9
10
11
function promiseFn(num) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (num) {
resolve("success");
} else {
reject("error");
}
}, 0);
});
}
  • 建立函釋後直接 return 一個 Promise 的實體物件,並且把之前寫的參數帶入。
  • 既然是非同步事件,典型的用法為 setTimeout
  • 在執行完非同步事件後,才會回傳結果。

執行上方函式,並給予真值,使用 then 取得正確的結果。

1
2
3
4
5
6
7
promiseFn(1)
.then((res) => {
console.log(res);
})
.catch((res) => {
console.log(res);
});

如果帶入的參數為 0 ,則會變失敗,就會由 catch 來呈現結果。

CodePen: https://codepen.io/hnzxewqw/pen/MWyRMGB?editors=1111