通过调用 $q.defer() 可以构建一个新的 deffered 实例。
deffered 对象用来将 Promise 实例与 标记任务状态(执行成功还是不成功)的 API 相关联。
promise – {Promise} —— 与延迟(deferred)相关联的 promise 对象。
当创建 deferred 实例时会创建一个新的 promise 对象,并可以通过 deferred.promise 得到该引用。
promise 对象的目的是在 deferred 任务完成时,允许感兴趣的部分取得其执行结果。
这个方法 返回一个新的promise 对象, 根据 successCallback , errorCallback的返回值进行解决或拒绝 。 它还通过 notifyCallback 方法的返回值进行通知。 promise 不能从notifyCallback方法得到解决或拒绝 。
因为在 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对象
链式调用内部的默认失败回调会向后传递异常,所以为避免麻烦,且不在意每一处的业务逻辑错误,不要在每一处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!