一、什麼是Promise Promise是對象,代表了一個函數最終可能的返回值或拋出的異常,就是用來非同步處理值的。 Promise是一個構造函數,自己身上有all、reject、resolve這幾個非同步方式處理值的方法,原型上有then、catch等同樣很眼熟的方法。 二、為什麼使用Promise ...
一、什麼是Promise
Promise是對象,代表了一個函數最終可能的返回值或拋出的異常,就是用來非同步處理值的。
Promise是一個構造函數,自己身上有all、reject、resolve這幾個非同步方式處理值的方法,原型上有then、catch等同樣很眼熟的方法。
二、為什麼使用Promise
有了Promise
對象,就可以把非同步操作以同步操作的流程表達出來,避免了層層嵌套的回調函數。此外,Promise
對象提供了統一的介面,使得控制非同步操作更加容易。
Promise
對象有以下2個特點:
1.對象的狀態不受外界影響。
Promise
對象代表一個非同步操作,有三種狀態:Pending(進行中)
、Resolved(已完成)
和Rejected(已失敗)
。只有非同步操作的結果,可以決定當前是哪一種狀態,任何其他操作都無法改變這個狀態。
2.一旦狀態改變,就不會再變,任何時候都可以得到這個結果。
Promise
對象的狀態改變,只有兩種可能:從Pending
變為Resolved
;從Pending
變為Rejected
。只要這兩種情況發生,狀態就凝固了,不會再變了,會一直保持這個結果。
三、如何創建一個Promise
先貼一段代碼:
define([ 'angularModule' ],function (app) { app.register.service('httpRequestService', ['$http', '$q', function ($http, $q) { return{ request: function (params) { var deferred = $q.defer(); $http({ method : params.method, url : params.url }).success( function (data) { deferred.resolve(data); } ).error( function(data){ deferred.reject(data); } ); return deferred.promise; } } }]) });
講一下$q服務
q服務是AngularJS中自己封裝實現的一種Promise實現。
要創建一個deferred對象,可以調用defer()方法:
var deferred = $q.defer(); //deffered上面暴露了三個方法,以及一個可以用於處理promise的promise屬性。 //promise屬性裡面又包含了then、catch、finally三個方法
在Promise中,定義了三種狀態:等待狀態,完成狀態,拒絕狀態。
deffered API
1.deffered 對象的方法
1.resolve(value):在聲明resolve()處,表明promise對象由pending狀態轉變為resolve。
2.reject(reason):在聲明resolve()處,表明promise對象由pending狀態轉變為rejected。
3.notify(value)
:在聲明notify()處,表明promise對象unfulfilled狀態,在resolve或reject之前可以被多次調用。
2.deffered 對象屬性
promise :最後返回的是一個新的deferred對象 promise 屬性,而不是原來的deferred對象。這個新的Promise對象只能觀察原來Promise對象的狀態,而無法修改deferred對象的內在狀態可以防止任務狀態被外部修改。
3.Promise API
當創建 deferred 實例時會創建一個新的 promise 對象,並可以通過 deferred.promise 得到該引用。
promise 對象的目的是在 deferred 任務完成時,允許感興趣的部分取得其執行結果。
4.promise 對象的方法
1.then(errorHandler, fulfilledHandler, progressHandler):then方法用來監聽一個Promise的不同狀態。errorHandler監聽failed狀態,fulfilledHandler監聽fulfilled狀態,progressHandler監聽unfulfilled(未完成)狀態。此外,notify 回調可能被調用 0到多次,提供一個進度指示在解決或拒絕(resolve和rejected)之前。
2.catch(errorCallback) —— promise.then(null, errorCallback) 的快捷方式
3.finally(callback) ——讓你可以觀察到一個 promise 是被執行還是被拒絕, 但這樣做不用修改最後的 value值。 這可以用來做一些釋放資源或者清理無用對象的工作,不管promise 被拒絕還是解決。
q常用的幾個方法:
- defer() 創建一個deferred對象,這個對象可以執行幾個常用的方法,比如resolve,reject,notify等
- all() 傳入Promise的數組,批量執行,返回一個promise對象
- when() 傳入一個不確定的參數,如果符合Promise標準,就返回一個promise對象。
all()方法
當批量的執行某些方法時,就可以使用這個方法。有了all,你就可以並行執行多個非同步操作,並且在一個回調中處理所有的返回數據。
用Promise.all來執行,all接收一個數組參數,裡面的值最終都算返回Promise對象。這樣,三個非同步操作的並行執行的,等到它們都執行完後才會進到then裡面。
那麼,三個非同步操作返回的數據哪裡去了呢?都在then裡面呢,all會把所有非同步操作的結果放進一個數組中傳給then,就是 下麵的results。所以下麵代碼的輸出結果就是:
var funcA = function(){ console.log("funcA"); return "hello,funA"; } var funcB = function(){ console.log("funcB"); return "hello,funB"; } $q.all([funcA(),funcB()]) .then(function(result){ console.log(result); });
執行的結果:
funcA
funcB
Array [ "hello,funA", "hello,funB" ]
when()方法
when方法中可以傳入一個參數,這個參數可能是一個值,可能是一個符合promise標準的外部對象。
var funcA = function(){ console.log("funcA"); return "hello,funA"; } $q.when(funcA()) .then(function(result){ console.log(result); });
當傳入的參數不確定時,可以使用這個方法。
hello,funA
四、鏈式請求
通過then()方法可以實現promise鏈式調用,因為then方法總是返回一個新的promise。
runAsync1() .then(function(data){ console.log(data); return runAsync2(); }) .then(function(data){ console.log(data); return runAsync3(); }) .then(function(data){ console.log(data); });
function runAsync1(){ var p = new Promise(function(resolve, reject){ //做一些非同步操作 setTimeout(function(){ console.log('非同步任務1執行完成'); resolve('隨便什麼數據1'); }, 1000); }); return p; } function runAsync2(){ var p = new Promise(function(resolve, reject){ //做一些非同步操作 setTimeout(function(){ console.log('非同步任務2執行完成'); resolve('隨便什麼數據2'); }, 2000); }); return p; } function runAsync3(){ var p = new Promise(function(resolve, reject){ //做一些非同步操作 setTimeout(function(){ console.log('非同步任務3執行完成'); resolve('隨便什麼數據3'); }, 2000); }); return p; }
運行結果: