今天在写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);