除了使用 Promise.resolve()
與 Promise.reject()
建立 Promise 外,也可使用 Promise Constructor 建立 Promise,其 Argument 為 Executor Function,提供了 resolve()
與 reject()
,可用來建立 Fulfilled Promise 與 Rejected Promise。
Version
macOS Catalina 10.15.5
VS Code 1.46.1
Quokka 1.0.307
ECMAScript 2015
Promise Constructor
let f = ms => x => new Promise((resolve, reject) => {
let inc = _ => {
let result = x + 1
return (result % 2) ?
resolve(`fulfilled: ${result}`) :
reject(`rejected: ${result}`)
}
setTimeout(inc, ms)
})
f(3000)(1) // ?
f(3000)(2) // ?
第 2 行
let inc = _ => {
let result = x + 1
return (result % 2) ?
resolve(`fulfilled: ${result}`) :
reject(`rejected: ${result}`)
}
inc()
是 synchronous function,若 + 1
結果是 奇數
,則回傳 Fulfilled Promise;若結果為 偶數
,則回傳 Rejected Promise。
第 10 行
setTimeout(inc, ms)
重點是 inc()
並不是立即執行,而是 setTimeout()
後 3
秒才執行,所以回傳是 Promise。
若要在 asynchronous function 產生 Promise,只靠 Promise.resolve()
與 Promise.reject()
寫不出來,必須使用 Promise Constructor,透過其 executor function 傳進 resolve()
與 reject()
,則可在 setTimeout()
的 callback 內由 resolve()
與 reject()
建立 Promise 回傳。
FileReader
let toBase64 = file => new Promise((resolve, reject) => {
let fileReader = new FileReader
fileReader.onload = _ => resolve(fileReader.result)
fileReader.onerror = e => reject(e)
fileReader.readAsDataURL(file)
})
toBase(x) // ?
Web API 的 FileReader
可將檔案轉成 Base64 String,但為 Event-based function,該如何改成 Promise-based 呢 ?
將檔案傳入 FileReader.readAsDataURL()
,會 asynchronous 在 onload
event 以 fileReader.result
獲得 Base64 String,在 onerror
event 取得 Error Object。
這種以 Event-based function 就特別適合使用 Promise Constructor,在 onload
event 以 resolve()
將 fileReader.result
包成 Fulfilled Promise,並在 onerror
event 以 reject()
將 Error Object 包成 Rejected Promise。
Conclusion
- 有兩個場景特別適合使用 Promise Constructor:
- 需同時產生 Fulfilled Promise 與 Rejected Promise 時
- 須將 Callback-based function 改成 Promise-based function 時,如
setTimeout()
- 需將 Event-based function 改成 Promise-based function 時,如
FileReader
Reference
Marius Schulz, Create a New Promise in JavaScript with Promise Constructor
MDN, Promise