EZTABLE IDEAS 是 EZTABLE 成員揮灑熱情和大家分享專業及創意的網誌。 EZTABLE 讓消費者 24 小時都可以在網路訂位全台灣最優質的餐廳,同時提供餐廳經營者 e 化的訂位管理系統 (雲端、iPad、智慧型手機)

Promise in JavaScript (ES6)

八月 01 2016 Published by under Engineering

* 什麼是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的文件

Related Posts Plugin for WordPress, Blogger...

No responses yet

發表迴響