### 11.2. 廣義回調管理
和其它框架一樣, ng 提供了廣義的異步回調管理的機制。 _$http_ 服務是在其之上封裝出來的。這個機制就是 ng 的 _$q_ 服務。
不過 ng 的這套機制總的來說實現得比較簡單,按官方的說法,夠用了。
使用的方法,基本上是:
- 通過 _$q_ 服務得到一個 _deferred_ 實例
- 通過 _deferred_ 實例的 _promise_ 屬性得到一個 _promise_ 對象
- _promise_ 對象負責定義回調函數
- _deferred_ 實例負責觸發回調
var TestCtrl = function($q){
var defer = $q.defer();
var promise = defer.promise;
promise.then(function(data){console.log('ok, ' + data)},
function(data){console.log('error, ' + data)});
//defer.reject('xx');
defer.resolve('xx');
}
了解了上面的東西,再分別看 _$q_ , _deferred_ , _promise_ 這三個東西。
### 11.2.1. $q
_$q_ 有四個方法:
- _$q.all()_ 合并多個 _promise_ ,得到一個新的 _promise_
- _$q.defer()_ 返回一個 _deferred_ 對象
- _$q.reject()_ 包裝一個錯誤,以使回調鏈能正確處理下去
- _$q.when()_ 返回一個 _promise_ 對象
_$q.all()_ 方法適用于并發場景很合適:
var TestCtrl = function($q, $http){
var p = $http.get('/json', {params: {a: 1}});
var p2 = $http.get('/json', {params: {a: 2}});
var all = $q.all([p, p2]);
p.success(function(res){console.log('here')});
all.then(function(res){console.log(res[0])});
}
_$q.reject()_ 方法是在你捕捉異常之后,又要把這個異常在回調鏈中傳下去時使用:
要理解這東西,先看看 _promise_ 的鏈式回調是如何運作的,看下面兩段代碼的區別:
var defer = $q.defer();
var p = defer.promise;
p.then(
function(data){return 'xxx'}
);
p.then(
function(data){console.log(data)}
);
defer.resolve('123');
var defer = $q.defer();
var p = defer.promise;
var p2 = p.then(
function(data){return 'xxx'}
);
p2.then(
function(data){console.log(data)}
);
defer.resolve('123');
從模型上看,前者是“并發”,后者才是“鏈式”。
而 _$q.reject()_ 的作用就是觸發后鏈的 _error_ 回調:
var defer = $q.defer();
var p = defer.promise;
p.then(
function(data){return data},
function(data){return $q.reject(data)}
).
then(
function(data){console.log('ok, ' + data)},
function(data){console.log('error, ' + data)}
)
defer.reject('123');
最后的 _$q.when()_ 是把數據封裝成 _promise_ 對象:
var p = $q.when(0, function(data){return data},
function(data){return data});
p.then(
function(data){console.log('ok, ' + data)},
function(data){console.log('error, ' + data)}
);
### 11.2.2. deferred
_deferred_ 對象有兩個方法一個屬性。
- _promise_ 屬性就是返回一個 _promise_ 對象的。
- _resolve()_ 成功回調
- _reject()_ 失敗回調
var defer = $q.defer();
var promise = defer.promise;
promise.then(function(data){console.log('ok, ' + data)},
function(data){console.log('error, ' + data)});
//defer.reject('xx');
defer.resolve('xx');
### 11.2.3. promise
_promise_ 對象只有 _then()_ 一個方法,注冊成功回調函數和失敗回調函數,再返回一個 _promise_ 對象,以用于鏈式調用。
- Introduction
- 關于AngularJS
- 關于本文檔
- 開始的例子
- 依賴注入
- 作用域
- 數據綁定與模板
- 數據->模板
- 模板->數據
- 數據->模板->數據->模板
- 模板
- 定義模板內容
- 內容渲染控制
- 節點控制
- 事件綁定
- 表單控件
- 模板中的過濾器
- 排序 orderBy
- 過濾列表 filter
- 其它
- 例子:表頭排序
- 例子:搜索
- 錨點路由
- 路由定義
- 參數定義
- 業務處理
- 定義模板變量標識標簽
- AJAX
- HTTP請求
- 廣義回調管理
- 工具函數
- 上下文綁定
- 對象處理
- 類型判定
- 其它服務
- 日志
- 緩存
- 計時器
- 表達式函數化
- 模板單獨使用
- 自定義模塊和服務
- 模塊和服務的概念與關系
- 定義模塊
- 定義服務
- 引入模塊并使用服務
- 附加模塊 ngResource
- 使用引入與整體概念
- 基本定義
- 基本使用
- 定義和使用時的占位量
- 實例
- AngularJS與其它框架的混用(jQuery, Dojo)
- 自定義過濾器
- 自定義指令directive
- 指令的使用
- 指令的執行過程
- 基本的自定義方法
- 屬性值類型的自定義
- Compile的細節
- transclude的細節
- 把節點內容作為變量處理的類型
- 指令定義時的參數
- Attributes的細節
- 預定義的 NgModelController
- 預定義的 FormController
- 示例:文本框
- 示例:模板控制語句 for
- 示例:模板控制語句 if/else