Promise

基礎語法
http://es6.ruanyifeng.com/#docs/promise
點評:
》注意理解Promise定義形式和調用形式的差異,定義時主要指定什麼狀況下(好比去後臺查詢到數據)能夠resolve或reject,調用時經過then指定resovle狀態下執行什麼回調方法,從而避免傳統的回調寫法層次太深的陷阱。
》注意理解執行順序,Promise 定義時當即執行,且此時調用resolve或reject方法不會阻止後續代碼的執行,而then方法指定的回調函數,將在當前腳本全部同步任務執行完纔會執行,即在本輪事件循環的末尾執行。
let promise = new Promise(function(resolve, reject) {
console.log('Promise');
resolve();
console.log('Promise end');
});
promise.then(function() {
console.log('resolved.');
});
console.log('Hi!');
輸出爲:
// Promise
// Promise end
// Hi!
// resolved
》Promise對象觸發resolve回調方法(即then綁定的參數)的調用是內部狀態化,這個變化能夠是主動的(調用resolve(參數是普通的值)),也能夠是被動的(調用resolve(參數爲另外一個Promise對象)),這時其內部狀態受另外一個Promise對象的內部狀態的影響。html

》Promise內部狀態一旦變爲Fullfilled就不會再變,且then綁定的兩個回調方法中返回的值,會自動包裝成一個已resolved的promise,從而會傳遞給鏈式綁定的下一個then方法的成功回調函數裏面去,而且上一個then回調函數返回的數據可被下一個then的回調函數接收。所以,不要在then方法裏面定義 reject 狀態的回調函數(即then的第二個參數),老是使用catch方法。由於reject回調中throw的error也是resolved狀態而catch不住,除非不是throw new Error('error!!!')而是return Promise.reject(new Error('error!!!'))。詳細分析參見下面的「最佳實踐」。
// good
promise
.then(function(data) { //cb
// success
return newdata // 這裏返回的數據可被下一個then回調接收
})
.then(function(data) { //cb
// success
})
.catch(function(err) {
// error
});
注意Node目前若是沒有使用catch方法指定錯誤處理的回調函數,Promise對象拋出的錯誤不會傳遞到外層代碼,即不會有任何反應。將來Node有計劃若是 Promise 內部有未捕獲的錯誤,會直接終止進程。
通常老是建議,Promise 對象後面要跟catch方法,這樣能夠處理 Promise 內部發生的錯誤。catch方法返回的仍是一個 Promise 對象,所以後面還能夠接着調用then方法。es6

》有時須要將現有對象轉爲 Promise 對象,Promise.resolve()方法就起到這個做用。
Promise.resolve()等價於下面的寫法。
Promise.resolve('foo')
// 等價於
new Promise(resolve => resolve('foo'))web

Promise.resolve方法的參數分紅四種狀況。
(1)參數是一個 Promise 實例
若是參數是 Promise 實例,那麼Promise.resolve將不作任何修改、原封不動地返回這個實例。json

(2)參數是一個thenable對象
Promise.resolve方法會將這個對象轉爲 Promise 對象,而後就當即執行thenable對象的then方法。
let thenable = {
then: function(resolve, reject) {
resolve(42);
}
};segmentfault

let p1 = Promise.resolve(thenable);
p1.then(function(value) {
console.log(value); // 42
});
上面代碼中,thenable對象的then方法執行後,對象p1的狀態就變爲resolved,從而當即執行最後那個then方法指定的回調函數,輸出 42。promise

(3)參數不是具備then方法的對象,或根本就不是對象
若是參數是一個原始值,或者是一個不具備then方法的對象,則Promise.resolve方法返回一個新的 Promise 對象,狀態爲resolved。
const p = Promise.resolve('Hello');
p.then(function (s){
console.log(s)
});
// Hello
上面代碼生成一個新的 Promise 對象的實例p。因爲字符串Hello不屬於異步操做(判斷方法是字符串對象不具備 then 方法),返回 Promise 實例的狀態從一輩子成就是resolved,因此回調函數會當即執行。Promise.resolve方法的參數,會同時傳給回調函數。app

(4)不帶有任何參數
Promise.resolve()方法容許調用時不帶參數,直接返回一個resolved狀態的 Promise 對象。異步

同理,Promise.reject(reason)方法也會返回一個新的 Promise 實例,該實例的狀態爲rejected。函數

異步加載圖片示例:
const getJSON = function(url) {
const promise = new Promise(function(resolve, reject){
const handler = function() {
if (this.readyState !== 4) {
return;
}
if (this.status === 200) {
resolve(this.response);
} else {
reject(new Error(this.statusText));
}
};
const client = new XMLHttpRequest();
client.open("GET", url);
client.onreadystatechange = handler;
client.responseType = "json";
client.setRequestHeader("Accept", "application/json");
client.send();post

});

return promise;
};

getJSON("/posts.json").then(function(json) {
console.log('Contents: ' + json);
}, function(error) {
console.error('出錯了', error);
});

》Bluebird 是一個功能豐富並且性能優異的 Promise 實現
https://www.ibm.com/developerworks/cn/web/wa-lo-use-bluebird-implements-power-promise/index.html

最佳實踐https://segmentfault.com/a/1190000014747362?utm_source=tag-newest

相關文章
相關標籤/搜索