1、先來看一段Demo,看完這個demo你可以思考下如果使用$.ajax如何處理同樣的邏輯,使用ng的promise有何優勢?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
var ngApp=angular.module( 'ngApp' ,[]); /******************************************************************* *
$q爲內置服務 ****************************************************************/ ngApp.factory( 'UserInfoService' ,[ '$http' , '$q' , function ($http,$q){ return { query: function (){ var defer=$q.defer(); //聲明延後執行 $http({method: 'GET' ,url: 'data/students.json' }). success( function (data,status,headers,config){ defer.resolve(data); //聲明執行成功 console.log( 'UserInfoService
success' ); }). error( function (data,status,headers,config){ defer.reject(); //聲明執行失敗 }); return defer.promise; //返回承諾,返回獲取數據的API } } }]); ngApp.controller( 'MainCtrl' ,[ '$scope' , 'UserInfoService' , function ($scope,UserInfoService){ var promise
= UserInfoService.query(); //同步調用,獲取承諾接口 promise.then( function (data){ $scope.user=data; //調用承諾接口resolove() console.log( 'MainCtrl
...' ); }, function (data){ $scope.user={error: '數據不存在。。。' }; //調用承諾接口reject(); }); }]); |
2、什麼是promise?
promise是一種用異步的方式處理值的方法,promise是對象,代表了一個函數最終可能的返回值或者拋出的異常,在與遠程對象打交道時我們可以把他看作是遠程對象的一個代理。 如果說是promise也是異步處理方式的一種,那麼我們會想起它和XHR和$.ajax有啥區別呢?
習慣上js使用閉包或者回調來相應非同步返回的數據,比如頁面加載之後的XHR請求。我們可以跟數據進行正常交互,就好像它已經返回了一樣,而不需要依賴回調函數的觸發。
那麼ng提出的promise是爲了解決什麼問題呢? 回調已經被使用了很長時間,通常如果有回調依賴其他還回調時將會時調試變得非常艱難,每一步調用之後都需要顯示處理錯誤。與之不同的是promise提供了另外一個抽象:這些函數返回promise對象。
從一定層面上看ng改變的不是簡單的改變代碼風格,而是讓我對一些思維習慣發起了反思和改善。
回調示例
1
2
3
4
5
6
|
User.get(fromId,{ success: function (){ user.friends.find(toId, function (){}) }, failure: function (){} }) |
ng promise示例
1
2
3
4
5
6
7
|
User.get(fromId). then( function (user){ }, function (err){ }). then( function (){}, function (){}); |
3、爲什麼使用promise
使用了promise的收穫之一是逃脫了回調的固定思維邏輯。promise讓異步處理的機制看上去更像是同步,基於同步函數我們可以按照預期來捕獲返回值和異常值。可以在程序中的任何時刻捕捉錯誤,並且繞過依賴於程序異常的後續代碼,我們不需要思考這個同步帶來的好處。因此使用promise的目的是:獲取功能組合和錯誤冒泡能力的同時,保持代碼異步運行的能力。
promise是頭等對象,自帶了一些約定。
- 只有一個resolve或者reject會被調用到。
- 如果promise被執行或者被拒絕了,依賴於他們的處理程序仍然會被調用。
- 處理程序總是會被異步調用。
4、如何創建promise
想要在angularjs中創建promise,可以使用內置的$q服務,$q服務在它的deferred API中提供了一些方法。
首先把它注入到你想使用它的對象中
1
2
3
4
|
angular.module( 'ngApp' ,[]). factory( 'UserInfoService' ,[ '$q' , function ($q){ //code
here }]) |
要創建一個deferred對象,可以調用defer()方法; var deferred= $q.defer();
deferred對象暴露了三個方法,以及一個可以用於處理promise的promise屬性。
- resolve(value)。 deferred.resolve({name:"Kobe",Age:36});
- reject(reason)。 deferred.reject("Can't update user");
- notify(value)。這個方法用promise的執行狀態進行響應。
- then(successFn,errFn,notifyFn)。
- catch(errFn)。
- finally(callback)。finally允許我們觀察promise的執行或者拒絕,而無需修改結果的值。通常就做一些資源的清理工作。
5、鏈式請求
1
2
3
4
5
|
GitHubService.then( function (data){ }).then( function (data){ $scope.Users=data; }); |