今天在写AngularJS Service,然后希望在Controller中使用Service提供Model。架构上,我希望Controller可以直接获得数据,因此有了“同步读取”数据的想法。但是,我们都知道,在前端做同步读取显然不是好的实践做法,毕竟JavaScript的很多良好体验都是通过异步请求实现的。而且,同步之后会严重影响前端的体验和性能。
AngularJS提供了一个内置Service $q,它提供了一种承诺/延后(promise/deferred)Promises对象是CommonJS工作组提出的一种规范,目的是为异步编程提供统一接口。简单说,它的思想是,每一个异步任务返回一个Promise对象,该对象有一个then方法,允许指定回调函数。比如,f1的回调函数f2,可以写成:
f1().then(f2);
f1要进行如下改写(这里使用的是jQuery的实现):
function f1(){
var dfd = $.Deferred();
setTimeout(function () {
// f1的任务代码
dfd.resolve();
}, 500);
return dfd.promise;
}
这样写的优点在于,回调函数变成了链式写法,程序的流程可以看得很清楚,而且有一整套的配套方法,可以实现许多强大的功能。
比如,指定多个回调函数:
f1().then(f2).then(f3);
再比如,指定发生错误时的回调函数:
f1().then(f2).fail(f3);
service层实践例子:
var _qryClByCltype= function(vcltype){
var deferred = $q.defer();
var query = "SELECT clname , cltype ,clrevel ,dtime ,context, futures,direction FROM tab_clremind "; //where cltype=? order by dtime limit 50
$cordovaSQLite.execute(db, query, []).then(function(res){
var clrecord=[];
if(res.rows.length>0) {
//$cordovaToast.showLongBottom('记录>0');
for(var i=0;i<res.rows.length;i++){
clrecord.push({
clname: res.rows.item(i).clname,
cltype: res.rows.item(i).cltype,
clrevel: res.rows.item(i).clrevel,
dtime: res.rows.item(i).dtime,
context: res.rows.item(i).context,
futures: res.rows.item(i).futures,
direction: res.rows.item(i).direction
});
}
//$cordovaToast.showLongBottom('clrecord.length='+$scope.clrecord.length);
}
/*
else{
//$cordovaToast.showLongBottom('tab_clremind表没有'+vcltype+"的记录");
}
*/
$cordovaToast.showLongBottom('clrecord.length='+clrecord.length);
deferred.resolve(clrecord);//传出去的数据
}, function (err) {
//$cordovaToast.showLongBottom('获取tab_clremind记录时出现异常'+err.message);
deferred.reject(err);
});
//$cordovaToast.showLongBottom('tab_clremind查询end");
return deferred.promise;;
}
Controller层同步调用
var promise =dbService.qryClByCltype("日内波段"); // 同步调用,获得承诺接口
promise.then(function(data) { // 调用承诺API获取数据 .resolve
$scope.tab1_clrecord=data;
}, function(err) { // 处理错误 .reject
$cordovaToast.showLongBottom('获取tab_clremind记录时出现异常'+err.message);
});
alert("$scope.tab1_clrecord.length="+$scope.tab1_clrecord.length);