promise出現的動機
在javascript的世界中,所有程式碼都是單執行緒執行的。
由於這個缺陷,導致所有的的網路操作,瀏覽器事件都是由非同步執行。非同步執行可以用回撥實現,ajax就是典型的非同步操作
如下程式碼在純JavaScript中實現它們並使用它們來包裝現有的非同步操作:
function readJSON(filename, callback){
fs.readFile(filename, 'utf8', function (err, res){
if (err) return callback(err);
try {
res = JSON.parse(res);
} catch (ex) {
return callback(ex);
}
callback(null, res);
});
}
複製程式碼
以上程式碼缺點
有很多,實現多次回撥會使我們的程式碼變得非常混亂。
promise描述
promise(承諾)
承諾背後的核心思想是承諾代表非同步操作的結果。
一個 Promise有以下幾種狀態:
- pending: 初始狀態,既不是成功,也不是失敗狀態。
- fulfilled: 意味著操作成功完成。
- rejected: 意味著操作失敗。
pending 狀態的 Promise 物件可能觸發fulfilled 狀態並傳遞一個值給相應的狀態處理方法,也可能觸發失敗狀態(rejected)並傳遞失敗資訊。當其中任一種情況出現時,Promise 物件的 then 方法繫結的處理方法(handlers )就會被呼叫(then方法包含兩個引數:onfulfilled 和 onrejected,它們都是 Function 型別。當Promise狀態為fulfilled時,呼叫 then 的 onfulfilled 方法,當Promise狀態為rejected時,呼叫 then 的 onrejected 方法, 所以在非同步操作的完成和繫結處理方法之間不存在競爭。
new Promise((resolve,reject)=>{
}).then((data)=>{
},err=>{
}).catch(()=>{
})
複製程式碼
promise私有方法
Promise.all(iterable)
這個方法返回一個新的promise物件,該promise物件在iterable引數物件裡所有的promise物件都成功的時候才會觸發成功,一旦有任何一個iterable裡面的promise物件失敗則立即觸發該promise物件的失敗。這個新的promise物件在觸發成功狀態以後,會把一個包含iterable裡所有promise返回值的陣列作為成功回撥的返回值,順序跟iterable的順序保持一致;如果這個新的promise物件觸發了失敗狀態,它會把iterable裡第一個觸發失敗的promise物件的錯誤資訊作為它的失敗錯誤資訊。Promise.all方法常被用於處理多個promise物件的狀態集合。
Promise.race(iterable)
當iterable引數裡的任意一個子promise被成功或失敗後,父promise馬上也會用子promise的成功返回值或失敗詳情作為引數呼叫父promise繫結的相應控制程式碼,並返回該promise物件
Promise.reject(reason)
返回一個狀態為失敗的Promise物件,並將給定的失敗資訊傳遞給對應的處理方法
Promise.resolve(value)
返回一個狀態由給定value決定的Promise物件。
promise原型方法
Promise.prototype.catch(onRejected)
新增一個拒絕(rejection) 回撥到當前 promise, 返回一個新的promise。當這個回撥函式被呼叫,新 promise 將以它的返回值來resolve,否則如果當前promise 進入fulfilled狀態,則以當前promise的完成結果作為新promise的完成結果.
Promise.prototype.then(onFulfilled, onRejected)
新增解決(fulfillment)和拒絕(rejection)回撥到當前 promise, 返回一個新的 promise, 將以回撥的返回值來resolve。
Promise.prototype.finally(onFinally)
新增一個事件處理回撥於當前promise物件,並且在原promise物件解析完畢後,返回一個新的promise物件。回撥會在當前promise執行完畢後被呼叫,無論當前promise的狀態是完成(fulfilled)還是失敗(rejected)
jQuery中的promise規範
jquery用deferred實現了Promise規範,$.Deferred是個什麼玩意呢?還是老方法,列印出來看看,先有個直觀印象:
var def = $.Deferred();
console.log(def);
複製程式碼
$.Deferred()返回一個物件,我們可以稱之為Deferred物件,上面掛著一些熟悉的方法如:
done、fail、then
等。jquery就是用這個Deferred物件來註冊非同步操作的回撥函式,修改並傳遞非同步操作的狀態。
Node.js的promise
安裝promise:
npm install promise --save
複製程式碼
然後你可以使用它將它載入到一個區域性變數中 require
var Promise = require('promise');
複製程式碼
"promise"庫還提供了一些與node.js互動的真正有用的擴充套件
var readFile = Promise.denodeify(require('fs').readFile);
function readJSON(filename, callback){
return readFile(filename, 'utf8')
.then(JSON.parse)
.nodeify(callback);
}
複製程式碼