Promise是異步編程的一個解決方案,相比傳統的解決方法——回調函數,使用Promise更爲合理和強大,避免了回調函數之間的層層嵌套,也使得代碼結構更爲清晰,便於維護。Promise 是一個對象,從他能夠獲取異步操做的消息,他也是一個容器,裏面包含着事件結束以後要進行的操做。javascript
Promise對象有兩個特色:java
pending
(進行中)、resolved
(已完成)、rejected
(已失敗),具體處於哪種狀態是由異步操做的結果來決定的,其餘的任何操做都沒法改變這個狀態。Promise是一個構造函數,生成一個實例。ajax
var promise = new Promise(function(resolve,reject){ if(/異步成功/){ resolve(val); }else{ reject(val); } }); promise.then(function(val){ /成功後執行的函數/ },function(error){ /失敗後執行的函數/ });
Promise構造函數接收一個函數做爲參數,這個函數有兩個參數resolve、reject,這兩個參數也是兩個函數,有javascript引擎提供,不須要本身實現。其中,resolve函數的做用是將Promise對象的狀態由"進行中"變爲"已完成",在異步操做成功的時候調用,並將異步操做的結果以參數的形式傳出,就是上例中的val
。reject函數的做用是將Promise對象的狀態由"進行中"變爲"已失敗",在異步操做失敗的時候調用,並將操做失敗的錯誤已參數的形式傳出。編程
Promise的實例能夠調用then
方法,then
方法有兩個函數做爲參數,第一個函數是Promise對象狀態變爲resoloved時執行的函數,第二個函數是Promise對象狀態變爲rejected時執行的函數,第二個參數是可選的。數組
一個典型的例子:異步讀取文件promise
function readFileFn(filename){ return new Promise(function(resolve,reject){ fs.readfile(filename,function(err,data){ if(err){ reject(err); }else{ resolve(data); } }); }); } readFileFn("./test.txt").then(function(data){ console.log(data.toString()); //其餘操做... },function(err){ console.log(err); });
then
方法能夠採用鏈式的寫法,即:異步
promise.then(...).then(...).then(..)
異步編程
具體的例子:函數
var promise = new Promse(function(resolve,reject){ resolve(1); //將Promise對象的狀態改成resolved,並傳遞參數1 }); promise.then(function(val){ console.log(val); // 1 return val*3; }).then(function(val){ console.log(val); //3 return val*3; }).then(function(val){ console.log(val); //9 });
then
方法裏省略第二個參數,而後在鏈式調用的尾部使用catch
方法來捕獲異步操做或者then
方法中的錯誤;readFileFn("./test.txt").then(function(data){ console.log(data.toString()); //其餘操做... }).catch(function(err){ console.log(err); }) //另外一種用法 var promise = new Promise(function(resolve,reject){ reject(new Error("test")); }); promise.then(function(val){ //... }).catch(function(err){ console.log(err); //.. });
var p = Promise.all([a,b,c]); //a,b,c都是Promise的實例
prototype
p最終的狀態由a,b,c三者決定:
1>.當a,b,c的狀態都是resolved時,p的狀態纔是resolved,此時a,b,c的返回值組成一個數組,傳給p的回調函數。
2>.只要 a,b,c中有一個狀態時reject,p的狀態就是reject,此時一個reject的實例的返回值會傳遞給p的回調函數。
var promises = [1,2,3,4].map(function(id){ return readFileFn("./test"+id+".txt"); //readFileFn()是上面聲明過的函數 }); Promise.all(promises).then(function(val){ //... }).catch(function(err){ //... });
var promise = Promise.resolve($.ajax("./test.txt"));
Promise.resolve()有四種類型的參數:
1>.Promise實例,那麼函數不會對參數作任何修改,原樣返回;
2>.普通對象,如同上例,會轉換成一個promise對象返回;
3>.非對象,即普通的變量,好比"hello"、2 等等,此時會返回一個新的Promise實例,狀態爲resolved(),"hello"會以參數的形式傳給
then
的第一個方法;
var p = Promise.resolve("hello"); p.then(function(val){ //此函數會當即執行 console.log(val); //hello });
4>.不帶參數,會直接返回一個Resolved狀態的Promise對象。
done()
方法,位於回調鏈的最尾端,用於捕獲錯誤。promise.then(function(){}).then(function(){}).catch(function(){}).done();
done()
的區別是能夠接受一個普通的回調函數做爲參數,且該函數必定會執行。