這篇文章講的不錯, angular $q 和 promise!!
--------------------------------------------------------------
通過調用 $q.defer() 可以構建一個新的 deffered 實例。
deffered 對象用來將 Promise 實例與 標記任務狀態(執行成功還是不成功)的 API 相關聯。
deffered 對象的方法
- resolve(value) ——傳入 value 解決派生的 promise。 如果 value 是一個通過 $q.reject 構造的拒絕對象(rejection) , 該promise 將被拒絕。
- reject(reason) ——拒絕派生的promise,並提供原因 。 這相當於通過 $q.reject構造的拒絕對象(rejection)作為參數傳遞給 resolve。
- notify(value) ——在 promise 執行的過程中提供狀態更新。 這在 promise 被解決或拒絕之前可能會被多次調用。
deffered 對象的屬性
promise – {Promise} —— 與延遲(deferred)相關聯的 promise 對象。
承諾 接口 | Promise API
當創建 deferred 實例時會創建一個新的 promise 對象,並可以通過 deferred.promise 得到該引用。
promise 對象的目的是在 deferred 任務完成時,允許感興趣的部分取得其執行結果。
promise 對象的方法
- then(successCallback, errorCallback, notifyCallback) ——不管 promise 是被處理還是被拒絕, 一旦結果可用,then 就會盡快地異步調用 成功/錯誤 回調函數 只要結果是可用的。 調用回調函數時傳遞單個參數: 結果 或拒絕的理由。 此外,notify 回調可能被調用 0到多次,以提供 提供一個進度指示,之前承諾解決或拒絕。
這個方法 返回一個新的promise 對象, 根據 successCallback , errorCallback的返回值進行解決或拒絕 。 它還通過 notifyCallback 方法的返回值進行通知。 promise 不能從notifyCallback方法得到解決或拒絕 。
- catch(errorCallback) —— promise.then(null, errorCallback) 的快捷方式
- finally(callback) ——讓你可以觀察到一個 promise 是被執行還是被拒絕, 但這樣做不用修改最后的 value值。 這可以用來做一些釋放資源或者清理無用對象的工作,不管promise 被拒絕還是解決。 更多的信息
因為在 ES3版本的JavaScript中 finally 是一個保留字關鍵字,不能作為屬性名,為了適配 IE8,您需要使用 promise['finally'](callback) 這種形式來調用該方法。
研究了一下$q回調服務,看來半天都是似懂非懂的樣子,感覺實現了異步加載的功能,還是動手試驗並記錄下來,如果不對歡迎指正(后台是ASP.Net Web API模擬的)
第一種情況的回調,對單個數據源的請求
myApp.factory('myService', function ($http, $q) {
return {
getAllData: function () {
//定義一個回調服務
var deferred = $q.defer();
$http.get('/API/Values')//此時獲取的是單個數據源
.success(function (result) {
//將結果委托回調函數
deferred.resolve(result);
})
.error(function (result) {
debugger;
});
//返回回調函數結果
return deferred.promise;
}
};
});
function FetchCtrl($scope, $http, $templateCache, myService, myServiceAll) {
$scope.fetch = function () {
var result = myService.getAllData();
//通過回調函數結果得到數據值
result.then(function (data) {
$scope.result = data;
};
}
}
第二種情況的回調,對多個數據源的請求,最后同時將多個結果集合並一起返回
//服務聲明
myApp.factory('myServiceAll', function ($http, $q) {
return {
getAllData: function () {
//定義一個回調服務
var deferred = $q.defer();
//定義兩個獲取的源路徑
var p1 = $http.get('/API/Values');
var p2 = $http.get('/API/Values/0');
$q.all([p1, p2])
.then(function (results) {
var aggregatedData = [];
angular.forEach(results, function (result) {
aggregatedData = aggregatedData.concat(result.data);
});
//將結果委托回調函數
deferred.resolve(aggregatedData);
});
//返回回調函數結果
return deferred.promise;
}
}
});
function FetchCtrl($scope, $http, $templateCache, myService, myServiceAll) {
$scope.fetch = function () {
//通過回調函數結果得到數據值
var result = myServiceAll.getAllData();
result.then(function (data) {
$scope.result = data;
})
};
}
方法簡介
$q service 四個方法函數 , 按照個人理解划分為三類。
-
非鏈式調用
$q.when(value)
傳遞變量值,promise.then()執行成功回調
$q.all(promises)
多個promise必須執行成功,才能執行成功回調,傳遞值為數組或哈希值,數組中每個值為與Index對應的promise對象。
-
錯誤信息傳遞
$q.reject(reason)
返回一個失敗原因,promise.then()執行失敗回調
-
鏈式調用
$q.defer()
返回一個deferred對象
- resolve(value) – 簡化說明 配置該deferred對象promise的成功調用函數參數
- reject(reason) – 簡化說明 配置該deferred對象promise的失敗調用函數參數
- promise - 簡化說明 配置后的promise對象
個人理解說明
鏈式調用內部的默認失敗回調會向后傳遞異常,所以為避免麻煩,且不在意每一處的業務邏輯錯誤,不要在每一處then()處聲明異常處理函數,在最后一個 then()中聲明即可。
promiseX.then(function(){}).then(function(){})
.then(function(val){},function(reason){})
如果在意每一處可能出現的業務邏輯錯誤,在回調中return $q.reject();傳遞錯誤.無論執行哪一個回調函數,如果內部沒有人為return $q.reject();,則若沒有執行錯誤,暨返回成功信號。
var deferred = $q.defer();
deferred.resolve(1);
var promiseA = deferred.promise;
promiseA
.then(function(val){$log.info(val);return ++val;})
.then(function(val){$log.info(val);return ++val;})
.then(
function(val){$log.info(val);return ++val;},
function(val){$log.info(val)}
);
鏈式調用完成后控制台打印出 1,2,3
var deferred = $q.defer();
deferred.resolve(1);
var promiseA = deferred.promise;
promiseA
.then(function(val){$log.info(val);return $q.reject(15);})
.then(function(val){$log.info(val);return ++val;})
.then(function(val){$log.info(val);return ++val;})
.then(function(val){$log.info(val);return ++val;})
.then(
function(val){$log.info(val);return ++val;},
function(val){$log.info(val)}
);
鏈式調用完成后控制台打印出 1,15,可以看出,第一個return $q.reject(15)之后,直到最后一個then()才有錯誤回調函數,所以異常一直傳遞到最后,中間的幾個then()沒有錯誤回調函數。
$q.when('I Love you!')
.then(function(value){$log.info(value)});
控制台打印出I Love you!;
$q.when($q.reject('I Hate you!'))
.then(null,function(value){$log.info(value)});
控制台打印出I Hate you!;
var promiseA = $q.when('I Love you!');
var promiseB = $q.when('Love story!');
var promiseC = $q.when("Let't get wet!");
$q.all([promiseA,promiseB,promiseC]).then(function(value){
value[0].then(function(value){$log.info(value);})
value[1].then(function(value){$log.info(value);})
value[2].then(function(value){$log.info(value);})
})
控制台打印出I Love you!,Love story!,"Let't get wet!