* 什麼是Promise? 為什麼需要Promise?
JavaScript和許多語言相比有些讓人難以捉模的特性
其中一個特別的特性是「非同步/異步(asynchronous)」
和其他同步的語言不一樣,JS的程式碼不一定會一行一行按照寫的順序執行
setTimeout(function() {
console.log(0)
}, 1000)
console.log(1)
在其他語言我們可能會看到先顯示0,過一秒後再顯示1
但在JavaScript之中這一段會先顯示1,過一秒後再顯示0
這種特性讓我們需要多做些處理來確保執行順序的正確
像是傳統的callback方式
function foo(callback) {
setTimeout(function() {
console.log(0)
if (callback) {
callback()
}
}, 1000)
}
function bar() {
console.log(1)
}
foo(bar);
像這樣顯示順序就會是01
我們可以把function傳遞到非同步function的參數中
讓他們在執行非同步的動作後進行想要的動作
但這種做法常常會產生所謂的callback hell,造成程式碼難以維護。
* Promise in ES6
雖然在ES6之前就有一些類似的Pattern(例如deffered)
但在這邊我們以ES6為主介紹
Promise是一個物件
在建立時你需要給他一個function,告訴他要做哪些事
例如,過一秒後顯示0
function toDo() {
setTimeout(function() {
console.log(0)
}, 1000)
}
同時我們也要決定這個function什麼時候會’被完成’
Promise在呼叫我們的toDo時會順便多傳兩個變數
分別是resolve和reject
決定’完成’以及’出現問題’的時機、以及到時該回傳的變數
function toDo(resolve, reject) {
setTimeout(function() {
console.log(0)
resolve(true)
}, 1000)
}
決定好這個Promise要做的事情後,我們就可以用它建立一個Promise,並且呼叫他
let promise = new Promise(toDo)
promise()
而Promise以及類似的物件(例如deffered)在執行後都會是一個thenable的物件
其中都會有一個.then()的function讓你告訴他接下來該做的事情
promise()
.then(function(success) {
console.log(100)
})
還記得上面我們resolve時傳了一個true嗎?
Promise內resolve所帶的值會傳到下一個then,變成下一個動作的參數
而Promise特別的地方在於
.then之後可以拿來做method chaining
或是再次return一個Promise
promise()
.then(function(result) {
return new Promise(function(resolve) {
resolve({
result: result
})
})
})
.then(JSON.stringify)
.then(function(jsonString) {
console.log(jsonString) // '{"result": true}'
})
假若是要同時處理數個Promise
亦可以用Promise.all()來處理
Promise.all([promise1, promise2, promise3])
.then(function(result) {
console.log(result[0]) // promise1的結果
console.log(result[1]) // promise2的結果
console.log(result[2]) // promise3的結果
})
Promise.all會在三個Promise都處理完(不分順序)之後,進行then的動作
可以拿來確保之前所有前置準備都已經做完
有時我們可能只是要建立一個Promise,但其實結果馬上就會拿到(並非非同步動作)
ES6也提供了Promise.resolve以及Promise.reject的方法
let promise = Promise.resolve('hi')
promise()
.then(console.log) // 'hi'
雖然處理Async還有ES6的Generater以及ES7的Async Function能使用
但Promise已經是很泛用,能解決許多問題,好理解,也不至於雜亂的寫法了。
要寫出好懂簡單的JavaScript,一定要搞懂Promise~!
更多Promise的用法,例如Error Handle,可以參考MDN的文件

發表迴響