jQuery
原本寫一個小動畫我們可能是這樣的
$('.animateEle').animate({
opacity:'.5'
}, 4000,function(){
$('.animateEle2').animate({
width:'100px'
},2000,function(){
$('.animateEle3').animate({
height:'0'
},2000);
});
});
但是如果我們使用promis對象的話,就可以使得代碼更加簡單易懂
var animate1 = function() {
return $('.animateEle1').animate({opacity:'.5'},4000).promise();
};
var animate2 = function() {
return $('.animateEle2').animate({width:'100px'},2000).promise();
};
var animate3 = function(){
return $('.animateEle3').animate({height:'0'},2000).promise();
};
$.when(animate1()).then(animate2).then(animate3);
對比上面兩段代碼,回調的形式相比promise,後期較難維護,層層嵌套,出錯不好定位,反直覺。
Promise對象方法
對於DOM,動畫,ajax相關方法,都可以使用 promise 方法。調用 promise 方法,返回的是 promise 對象。可以鏈式調用 promise 方法。
比如jquery中的ajax的 $.post $.get $.ajax 等方法,實際上都是默認調用了promise方法,然後返回了一個promise對象
promise對象常見的方法有三個 : done , fail , then 。
$.get('/',{}).done(function(data){
console.log('success');
}).fail(function(){
console.log('fail');
});
query 這裏的接口方法太多了,就跟早期的事件方法綁定一樣, live , delegate , bind ,最終還是歸爲 on。
deferred對象方法
var promisepbj = new $.Deferred();
promisepbj.done(function() {
console.log('haha,done');
}).fail(function() {
console.log('失敗了');
}).always(function(res) {
console.log('我總是被執行啦');
});
//使用resolve或者reject就可以調用defferred對象了
promisepobj.resolve();
//promisepobj.reject();
resolve 方法會觸發 done 的回調執行, reject 會觸發 fail 的回調,對於 always 方法,deferred 對象,無論是 resolve 還是 reject ,都會觸發該方法的回調。
ES6 Promise
前面講了很多jquery的promise實現,$.Deferred 和 ES2015 的 Promise 是不同的東西,因爲前者不符合 Promises/A+ 規範。 Promise 對象在 EMCAScript 2015 當中已經成爲標準。現在要來談談馬上要成爲主流趨勢的es6原生promise對象,首先貼一個很詳細的es6 promise的小書,基本你知道的不知道都在裏面 http://liubin.org/promises-book/#introduction。
阮一峯大神的關於ES6的promise解釋 http://es6.ruanyifeng.com/#docs/promise。
定義
所謂Promise,簡單說就是一個容器,裏面保存着某個未來纔會結束的事件(通常是一個異步操作)的結果。
特點:
- 有三種狀態:Pending(進行中)、Resolved(已完成,又稱Fulfilled)和Rejected(已失敗)。
- 一旦狀態改變,就不會再變,任何時候都可以得到這個結果。Promise對象的狀態改變,只有兩種可能:從Pending變爲Resolved和從Pending變爲Rejected。只要這兩種情況發生,狀態就凝固了,會一直保持這個結果。就算改變已經發生了,你再對Promise對象添加回調函數,也會立即得到這個結果。這與事件(Event)完全不同,事件的特點是,如果你錯過了它,再去監聽,是得不到結果的。
var promise = new Promise(function(resolve, reject) {
// ... some code
if (/* 異步操作成功 */){
resolve(value);
} else {
reject(error);
}
});
then方法
then方法可以接受兩個回調函數作爲參數。第一個回調函數是Promise對象的狀態變爲Resolved時調用,第二個回調函數是Promise對象的狀態變爲Reject時調用。其中,第二個函數是可選的,不一定要提供。這兩個函數都接受Promise對象傳出的值作爲參數。
function timeout(ms) {
return new Promise((resolve, reject) => {
setTimeout(resolve, ms, 'done');
});
}
timeout(100).then((value) => {
console.log(value);
});
異常處理
異常處理一直是回調的難題,而promise提供了非常方便的catch方法:在一次promise調用中,任何的環節發生reject,都可以在最終的catch中捕獲到:
Promise.resolve().then(function(){
return loadImage(img1);
}).then(function(){
return loadImage(img2);
}).then(function(){
return loadImage(img3);
}).catch(function(err){
//錯誤處理
})
基本的 api
- Promise.resolve()
- Promise.reject()
- Promise.prototype.then()
- Promise.prototype.catch()
- Promise.all()
- Promise.race()
具體的很多的用法可以參考阮一峯的 http://es6.ruanyifeng.com/#docs/promise 入門教程