在看AngularJS的一本教材時,某章忽然遇到了$q服務的使用。也許是書的編排問題——將成網狀互相依賴的模塊用線性順序書寫——總之我是始終搞不明白為何要這么用,用了有什么好處。
沒有后端的前端如同空中樓閣。我用node.js和mongodb搞了一個簡單的restful服務,前端用AngularJS。經過一遍遍的排錯,最終差不多理解了$q的用法和優點。
不使用$q
服務
app.factory('BokanWork', ['$resource', function($resource){ return $resource('api/bokanwork/:id', {}); }]);
控制器,注入服務BokanWork
app.controller('BokanWorkListCntl', ['$scope', 'BokanWork', function($scope, BokanWork){ $scope.bokanWorkList = BokanWork.query(); }]);
顯示問題:
路由跳轉后才進行數據庫訪問,數據區域會出現短暫空白。
使用$q
服務
注入服務$q和BokanWork,創建promise服務MultiBokanWorkLoader。
{id: '@_id'}的意思是說,在POST/DELETE等請求時,將對象里的_id字段(mongodb的ObjectId)提取出來,填補在url對應的id里。
順便一提,Node.JS某本教材上是用PUT請求進行更新……這里我給改成POST咯……
services.factory('BokanWork', ['$resource', function($resource){ return $resource('api/bokanwork/:id', {id: '@_id'}); }]); services.factory('MultiBokanWorkLoader', ['BokanWork', '$q', function(BokanWork, $q){ return function() { var delay = $q.defer(); BokanWork.query(function(works){ delay.resolve(works); }, function(){ delay.reject('Unable to fetch BokanWork lists'); }); return delay.promise; }; }]);
路由配置。
resolve配置在promise解決后要注入的參數bokanWorkList。
when('/bokanwork', { templateUrl: 'tpl/bokanwork_list.html', controller: 'BokanWorkListCntl', resolve: { bokanWorkList: function(MultiBokanWorkLoader) { return MultiBokanWorkLoader(); } } })
控制器,注意參數bokanWorkList,是在路由配置注入的。
controllers.controller('BokanWorkListCntl', ['$scope', 'bokanWorkList', function($scope, bokanWorkList){ $scope.bokanWorkList = bokanWorkList; $scope.remove = function(index){ $scope.bokanWorkList[index].$remove(function(){ $scope.bokanWorkList.splice(index, 1); }); }; }]);
優勢:在數據獲取之后(即promise resolve之后)才進行路由跳轉,數據區域不會空白。