$q是Angular的一種內置服務,它可以使你異步地執行函數,并且當函數執行完成時它允許你使用函數的返回值(或異常)。
$q的其他方法
$q.when(value)//傳遞變量值,PRomise.then()執行成功回調//接收第一個參數為一個任意值或者是一個promise對象,//其他3個同promise的then方法,返回值為一個promise對象。//第一個參數若不是promise對象則直接運行success回調且消息為這個對象,//若為promise那么返回的promise其實就是對這個promise類型的參數的一個包裝而已,//被傳入的這個promise對應的defer發送的消息,//會被我們when函數返回的promise對象所接收到。$q.all(promises)//多個promise必須執行成功,才能執行成功回調,//傳遞值為數組或哈希值,//數組中每個值為與Index對應的promise對象。//參數接收為一個promise數組,//返回一個新的單一promise對象,//當這些promise對象對應defer對象全部解決這個單一promise對象才會解決,//當這些promise對象中有一個被reject了,//這個單一promise同樣的被reject了。defer的字面意思是延遲,$q.defer() 可以創建一個deferred實例(延遲對象實例)。defer主要是用來發送消息的。
deferred 實例旨在暴露派生的Promise 實例,以及被用來作為成功完成或未成功完成的信號API,以及當前任務的狀態。這聽起來好復雜的樣子,總結$q, defer, promise三者之間的關系如下所示。
var deferred = $q.defer(); //通過$q服務注冊一個延遲對象 deferredvar promise = deferred.promise; //通過deferred延遲對象,//可以得到一個承諾promise,//而promise會返回當前任務的完成結果defer的方法:
deferred.resolve(value)成功解決(resolve)了其派生的promise。 參數value將來會被用作
promise.then( successCallback(value){...}, errorCallback(reason){...}, notifyCallback(notify){...} )中successCallback函數的參數。deferred.reject(reason)未成功解決其派生的promise。 參數reason被用來說明未成功的原因。此時deferred實例的promise對象將會捕獲一個任務未成功執行的錯誤,
promise.catch(errorCallback(reason){...})。補充一點,promise.catch(errorCallback)實際上就是promise.then(null, errorCallback)的簡寫。notify(value)更新promise的執行狀態. (翻譯的不好,原話是provides updates on the status of the promise’s execution)
defer的小例子:
function asyncGreet(name) { var deferred = $q.defer(); //通過$q.defer()創建一個deferred延遲對象, //在創建一個deferred實例時, //也會創建出來一個派生的promise對象, //使用deferred.promise就可以檢索到派生的promise。 deferred.notify('About to greet ' + name + '.'); //延遲對象的notify方法。 if (okToGreet(name)) { deferred.resolve('Hello, ' + name + '!'); //任務被成功執行 } else { deferred.reject('Greeting ' + name + ' is not allowed.'); //任務未被成功執行 } return deferred.promise; //返回deferred實例的promise對象}function okToGreet(name) { //只是mock數據,實際情況將根據相關業務實現代碼 if(name == 'Superman') return true; else return false;}var promise = asyncGreet('Superman'); //獲得promise對象//promise對象的then函數會獲得當前任務//也就是當前deferred延遲實例的執行狀態。//它的三個回調函數分別會在resolve(), //reject() 和notify()時被執行promise.then(function(greeting) { alert('Success: ' + greeting);}, function(reason) { alert('Failed: ' + reason);}, function(update) { alert('Got notification: ' + update);});當創建一個deferred實例時,promise實例也會被創建。通過deferred.promise就可以檢索到deferred派生的promise。
promise的目的是允許interested parties 訪問deferred任務完成的結果。 promise 是 Js異步編程模式的一種模式,以同步操作的流程形式來操作異步事件,避免了層層嵌套,可以鏈式操作異步事件。
按照CommonJS的約定,promise是一個與對象交互的接口,表示一個動作(action)的結果是異步的,而且在任何給定的時間點上可能或不可能完成。(這句話好繞口,我的理解是promise相當于一個承諾,承諾你這個任務在給定的時間點上可能會完成,也可能完成不了。如果完成了那就相當于resolve, 如果未完成就相當于reject。不知道這樣理解對不對?)
每個任務都有三種狀態:未完成(pending)、完成(fulfilled)、失敗(rejected)。
pending狀態:可以過渡到履行或拒絕狀態。 fulfilled狀態:不能變為其他任何狀態,而且狀態不能改變,必須有value值。 rejected狀態:不能變為其他任何狀態,而且狀態不能改變,必須有reason。 狀態的轉移是一次性的,狀態一旦變成fulfilled(已完成)或者failed(失敗/拒絕),就不能再變了。
deffered 對象的方法: resolve(value):在聲明resolve()處,表明promise對象由pending狀態轉變為resolve。 向promise對象異步執行體發送消息告訴他我已經成功完成任務,value即為發送的消息。 reject(reason):在聲明resolve()處,表明promise對象由pending狀態轉變為rejected。 向promise對象異步執行體發送消息告訴他我已經不可能完成這個任務了,value即為發送的消息。 notify(value) :在聲明notify()處,表明promise對象unfulfilled狀態,在resolve或reject之前可以被多次調用。 向promise對象異步執行體發送消息告訴他我現在任務完成的情況,value即為發送的消息。
這些消息發送完promise會調用現有的回調函數。
deffered 對象屬性:
promise :最后返回的是一個新的deferred對象 promise 屬性,而不是原來的deferred對象。這個新的Promise對象只能觀察原來Promise對象的狀態,而無法修改deferred對象的內在狀態可以防止任務狀態被外部修改。
promise 的方法:
then(successCallback, errorCallback, nitifyCallback)//根據promise被resolve/reject,//或將要被resolve/reject,調用successCallback/errorCallback。//then方法用來監聽一個Promise的不同狀態。errorHandler監聽failed狀態,//fulfilledHandler監聽fulfilled狀態,//progressHandler監聽unfulfilled(未完成)狀態。//此外,notify 回調可能被調用0到多次,提供一個進度指示在解決或拒絕(resolve和rejected)之前。catch(errorCallback) // then(null, errorCallback)的縮寫。finally(callback, notifyCallback)//讓你可以觀察到一個 promise 是被執行還是被拒絕, //但這樣做不用修改最后的 value值。 //這可以用來做一些釋放資源或者清理無用對象的工作,//不管promise 被拒絕還是解決。補充說明:
promise.then()會返回一個新的衍生promise,形成promise鏈。
例如:
promiseB = promiseA.then(function(result) { return result + 1;});// promiseB will be resolved immediately // after promiseA is resolved and its value// will be the result of promiseA incremented by 1// promiseB 將會在處理完 promiseA 之后立刻被處理, // 并且其 value值是promiseA的結果增加1$http 服務只是簡單封裝了瀏覽器原生的xmlHttpRequest對象,接收一個參數,這個參數是一個對象,包含了用來生成HTTP請求的配置內容,這個函數返回一個promise對象,具有success和error方法。
$http服務的使用場景:
var promise = $http({ method:"post", // 可以是get,post,put, delete,head,jsonp;常使用的是get,post url:"./data.json", //請求路徑 params:{'name':'lisa'}, //傳遞參數,字符串map或對象,轉化成?name=lisa形式跟在請求路徑后面 data:blob, //通常在發送post請求時使用,發送二進制數據,用blob對象。}).success(function(data){//響應成功操作}).error(function(data){//響應失?。憫藻e誤狀態返回)操作})//或$http({url:'data.json',method:'GET'}).success(function(data,header,config,status){//響應成功}).error(function(data,header,config,status){//處理響應失敗});then()函數:可以使用then()函數來處理$http服務的回調,then()函數接受兩個可選的函數作為參數,表示success或error狀態時的處理,也可以使用success和error回調代替:
then(successFn, errFn, notifyFn)無論promise成功還是失敗了,當結果可用之后, then都會立刻異步調用successFn或者errFn。這個方法始終用一個參數來調用回調函數:結果,或者是拒絕的理由。 在promise被執行或者拒絕之前, notifyFn回調可能會被調用0到多次,以提供過程狀態的提示.
處理回調方式一:promise.then
promise.then(function(resp){//響應成功時調用,resp是一個響應對象}, function(resp) {// 響應失敗時調用,resp帶有錯誤信息});then()函數接收的resp(響應對象)包含5個屬性:
data(字符串或對象):響應體status:相應http的狀態碼,如200headers(函數):頭信息的getter函數,可以接受一個參數,用來獲取對應名字的值config(對象):生成原始請求的完整設置對象statusText:相應的http狀態文本,如”ok”或者使用success/error方法,使用。 處理回調方式二:promise.success/error
//成功處理promise.success(function(data, status, headers, config){ // 處理成功的響應});// 錯誤處理promise.error(function(data, status, headers, config){// 處理非成功的響應});兩種方法的區別:then()方法與其他兩種方法的主要區別是,它會接收到完整的響應對象,而success()和error()則會對響應對象進行析構。
index.html
<!doctype html><html lang="en"><head> <meta charset="UTF-8"> <title>$http request test </title> <script src="http://sandbox.runjs.cn/uploads/rs/376/pbcx3e1z/angular.min.js"></script> <script src="http://sandbox.runjs.cn/uploads/rs/376/pbcx3e1z/angular-route.min.js"></script> <script src="app.js"></script></head><body><div data-ng-app="myApp" data-ng-controller="myAppController" data-ng-init="loadData()"> <table> <thead> <tr> <th>名稱</th> <th>屬性</th> </tr> </thead> <tbody> <tr data-ng-repeat="data in myData"> <td>{{data.name}}</td> <td>{{data.attr}}</td> </tr> </tbody> </table></div></body></html>app.js
var myHttpApp = angular.module("myApp", []);myHttpApp.controller("myAppController", function ($q, $http, $scope) { var deffer = $q.defer(); var data = new Blob([{ "name": "zhangsan" }]); $scope.loadData = function () { var promise = $http({ method: "post", url: "./data.json", cache: true }).success(function (data) { deffer.resolve(data); }).error(function (data) { deffer.reject(data); }); promise.then(function (data) {/*//響應成功時調用,data是一個響應對象*/ $scope.myData = data.data; }); /*promise.success(function(data){ $scope.myData = data; })*/ }})data.json
[ {"name":"zhangsan","attr":"China"}, {"name":"lisa","attr":"USA"}, {"name":"Bob","attr":"UK"}, {"name":"Jecy","attr":"Jepan"}]效果
參考:
淺談Angular的 $q, defer, promise
AngularJS的$http服務的應用
AngularJS中$http服務的簡單用法
新聞熱點
疑難解答