ES6學習歷程 18 — ES6 Promise
ES6 Promise
Promise 是構造函數,構造函數是當要創建一個實例時必須使用new關鍵字,這樣才能調用構造函數。
Promise 的三種狀態:
1. pending — 等待中
2. fulfilled — 事件完成
3. rejected — 事件失敗
Promise 語法:
let completed = true;let promise = new Promise(function (resolve, reject) { if (completed) { resolve("I have completed learning JS."); } else { reject("I haven’t completed learning JS yet."); }});
Promise建立同時,必須傳入一個函式作為參數(executor function),此函式的參數包含 resolve, reject,這兩個方法分別代表成功與失敗的回傳結果,特別注意這兩個僅能回傳其中之一,回傳後表示此 Promise 事件結束。
promise.then()
then() 會回傳一個新的Promise物件。 then() 方法接受兩個函數作為參數:
- 第一個函數是當 Promise 狀態變為成功時會被調用
- 第二個函數是當 Promise 狀態變為失敗時會被調用,這個是選擇性的不一定需要
promise.then(function(value) { // 當狀態是 fulfilled (成功) 時,執行這個函數 // value 是透過 resolve() 傳進來的參數}, function(error) { // 當狀態是 rejected (失敗) 時,執行這個函數 // error 是透過 reject() 傳進來的參數});
promise. catch()
catch() 用於捕捉錯誤。
promise.then(function(value) { // …}).catch(function(error) { // 處理 promise 和 前一個回調函數(then) 運行時發生的錯誤 console.log('發生錯誤!', error);});
若promise物件狀態變為resolved,則會調用then()方法指定的回調函數;如果異步操作抛出錯誤,狀態就會變為rejected,此時就會調用catch() 方法指定的回調函數,處理這個錯誤。另外,then() 方法指定的回調函數,如果運行中抛出錯誤,也會被catch() 方法捕獲。
promise 物件的錯誤具有“冒泡”性質,會一直向後傳遞,直到被捕獲為止。也就是說,錯誤總是會被下一個catch捕獲。
所以,不要在then() 方法裡面定義 reject 狀態的回調函數(即then的第二個參數),而是使用catch() 方法,如下:
// badpromise.then(function(data) { // success}, function(err) { // error});
// goodpromise.then(function(data) { // success}).catch(function(err) { // error});
Chaining
後面的 then() 會接收前一個 then() 的 return value 當作參數。如果 return value 的型態不是 promise,會先執行 promise.resolve()。
var promise= new Promise(function(resolve, reject) { resolve(10);});promise.then(function(result) { console.log(result); // 10 return result * 2;}).then(function(result) { console.log(result); // 20 return result * 3;}).then(function(result) { console.log(result); // 60 return result * 4;});// 10// 20// 60
promise. all()
用於將多個 promise物件包裝成一個新的 promise 物件。
var p1 = Promise.resolve(3);var p2 = 1337;var p3 = new Promise(function(resolve, reject) { setTimeout(resolve, 100, 'foo');});Promise.all([p1, p2, p3]).then(function(values) { console.log(values);});// 會顯示 [3, 1337, "foo"]
- p1、p2、p3都是 Promise 物件,如果不是,就會先調用promise.resolve() 方法,將參數轉為 promise物件,再進一步處理。
- promise.all() 方法的參數可以不是陣列,但必須具有 Iterator 接口,且回傳的每個成員都是 promise 物件。
promise. race()
和 Promise.all() 一樣用來將多個 Promise 物件包裝成一個 Promise 物件。
不同的地方在於,只要它包含的所有 Promise 物件其中任何一個的狀態先改變,race Promise 物件的狀態就會跟著改變,率先改變狀態的 Promise 物件參數會直接傳給 race Promise 物件的 callback。
var p1 = new Promise(function(resolve, reject) {setTimeout(resolve, 500, 'one');});var p2 = new Promise(function(resolve, reject) {setTimeout(resolve, 100, 'two');});Promise.race([p1, p2]).then(function(value) {console.log(value);});// "two",因為 p2 比較快被 resolve
promise. resolve ()
將一個物件轉型為 promise物件,然後立刻執行回調函數
promise. reject ()
將一個物件轉型為 promise物件,然後立刻執行回調函數