# AngularJS項目開發技巧之利用Service&Promise&Resolve解決圖片預加載問題(后記)
### 前言
在“AngularJS項目開發技巧之圖片預加載”一文中,自己曾經天真的認為提升服務端帶寬就可以解決圖片加載問題。但自己的想法錯了,通過閱讀破狼的書《AngularJS深度剖析與最佳實踐》,隱隱察覺到是自己的項目架構出現了問題。存在很多待優化的地方。其書中這樣寫到“如果在實例化控制器之前,需要準備一些特定數據,或者有條件的阻止進入路由,那么可以在$routeProvider中配置Resolve屬性來解決。”
### 注:預載入Resolve
使用預載入功能,開發者可以預先載入一系列依賴或者數據,然后注入到控制器中。在ngRoute中resolve選項可以允許開發者在路由到達前載入數據保證(promises)。在使用這個選項時比使用angular-route有更大的自由度。
預載入選項需要一個對象,這個對象的key即要注入到控制器的依賴,這個對象的value為需要被載入的factory服務。
如果傳入的是字符串,angular-route會試圖匹配已經注冊的服務。如果傳入的是函數,該函數將會被注入,并且該函數返回的值便是控制器的依賴之一。如果該函數返回一個數據保證(promise),這個數據保證將在控制器被實例化前被預先載入并且數據會被注入到控制器中。
### 思路
將圖片下載耗時操作做異步處理。圖片下載代碼如下:
~~~
try?{??
var?data?=?{};??
appCallServer($http,?"9101",?data,??
//success?function??
function(data)?{??
console.log("9101:"?+?JSON.stringify(data.data));??
var?adpic?=?new?Array;??
for?(var?i?=?0;?i?
adpic[i]?=?data.data[i].url;??
}??
$scope.adpic?=?adpic;??
return?true;??
},??
//?fail?function??
function(data)?{??
$ionicLoading.show({??
template:?"查詢廣告失敗,請檢查您的網絡連接"??
});??
$timeout(function()?{??
$ionicLoading.hide();??
},?1200);??
return?false;??
});??
}?catch?(error)?{??
$scope.showAlert1("call:"?+?error.message);??
return?false;??
}??
~~~
整理后的代碼如下:
路由:
~~~
.state('tab.find_med',?{??
url:?"/find_med",??
views:?{??
'tab-find_med':?{??
templateUrl:?"find_medicine.html",??
controller:?'find_med_contrller',??
resolve:{??
adpic:function(){??
var?data?=?{};??
appCallServer($http,?"9101",?data,??
//success?function??
function(data)?{??
console.log("9101_resolve:"?+?JSON.stringify(data.data));??
var?adpic?=?new?Array;??
for?(var?i?=?0;?i?
adpic[i]?=?data.data[i].url;??
}??
return?adpic;??
},??
//?fail?function??
function(data)?{??
$ionicLoading.show({??
template:?"查詢廣告失敗,請檢查您的網絡連接"??
});??
$timeout(function()?{??
$ionicLoading.hide();??
},?1200);??
return?false;??
});??
}??
}??
}??
}??
})??
~~~
控制器:
~~~
$scope.getadpic?=?function()?{??
$scope.adpic?=?adpic;??
};??
$scope.getadpic();??
~~~
執行程序,查看效果,提示如下錯誤:

unpr全稱是Unknown?Provider,也就是說沒有找到注入的東西。
找了半天忽然醒悟了,resolve中的對象只有在相應的控制器中才可以獲取到,而自己之前是在別的控制器中添加的resolve對象,難怪總是報服務未注入的錯誤呢。正確的代碼如下:
路由:
~~~
$stateProvider??
.state('tab',?{??
url:?"/tab",??
templateUrl:?"tabs.html",??
controller:?'tabsCtrl',??
resolve:{??
adpic:function(){??
return?"www";??
}??
}??
})??
~~~
控制器:
~~~
myCtrl.controller('tabsCtrl',?function($scope,?$rootScope,?$http,?$location,...?$timeout,?adpic)?{
...
$scope.getadpic?=?function()?{
console.log("adpic.........."?+?adpic);
};
$scope.getadpic();
}
~~~
所以一定要掌握原理。不要茫然。
添加以上代碼后,HBuilder報如下錯誤:
?
通過參考網絡文獻,優化后的代碼如下:
~~~
//?利用Factory單例特性創建服務??
myModule.factory('myAdpicService',function($http,?$q){??
???
return?{??
getAdpic:?function()?{??
var?d?=?$q.defer();??
var?data?=?{};??
appCallServer($http,?"9101",?data,??
//success?function??
function(data)?{??
console.log("9101_resolve:"?+?JSON.stringify(data.data));??
var?adpic?=?new?Array;??
for?(var?i?=?0;?i?
adpic[i]?=?data.data[i].url;??
}??
console.log("adpic___________:"?+?adpic);??
d.resolve(adpic);??
},??
//?fail?function??
function(data)?{??
$ionicLoading.show({??
template:?"查詢廣告失敗,請檢查您的網絡連接"??
});??
$timeout(function()?{??
$ionicLoading.hide();??
},?1200);??
d.reject(data);??
});??
return?d.promise;??
}??
}??
});"color:?rgb(62,?75,?83);?font-family:?Arial,?Helvetica,?sans-serif;?background-color:?rgb(255,?255,?255);">???
~~~
~~~
"color:#ff0000;">$stateProvider??
.state('tab',?{??
url:?"/tab",??
templateUrl:?"tabs.html",??
controller:?'tabsCtrl',??
resolve:{??
adpicSunny:function(myAdpicService)?{??
???????return?myAdpicService.getAdpic();??
}??
????}??
}??
~~~
控制器中的代碼不做任何變化。
### 代碼回顧
以上代碼通過定義一個獨立的service的方式來使用resolve?key,并且使用service來相應返回所需的數據(這種方式更容易測試)。并且對于較耗時的圖片加載操作做異步處理。這與[Android](http://lib.csdn.net/base/15)中的設計思想一致。至此,圖片預加載問題成功解決。
### 有圖有真相
?
### 參考文獻
1.[http://www.bkjia.com/Javascript/1043828.html](http://www.bkjia.com/Javascript/1043828.html)
2.[http://www.bubuko.com/infodetail-828239.html](http://www.bubuko.com/infodetail-828239.html)
3.[http://my.oschina.net/tanweijie/blog/295255](http://my.oschina.net/tanweijie/blog/295255)
### 美文美圖
??
- 前言
- (一)深入理解ANGULARUI路由_UI-ROUTER
- (二)AngularJS路由問題解決
- (四)ANGULAR.JS實現下拉菜單單選
- (五)Angular實現下拉菜單多選
- (六)AngularJS+BootStrap實現彈出對話框
- (七)實現根據不同條件顯示不同控件
- (十)AngularJS改變元素顯示狀態
- (十四)AngularJS靈異代碼事件
- (十七)在AngularJS應用中實現微信認證授權遇到的坑
- (十八)在AngularJS應用中集成科大訊飛語音輸入功能
- (十九)在AngularJS應用中集成百度地圖實現定位功能
- (二十一)Angularjs中scope與rootscope區別及聯系
- (二十三)ANGULAR三宗罪之版本陷阱
- (二十四)AngularJS與單選框及多選框的雙向動態綁定
- (二十五)JS實現導入文件功能
- (二十七)實現二維碼信息的集成思路
- (二十八)解決AngualrJS頁面刷新導致異常顯示問題
- (二十九)AngularJS項目開發技巧之localStorage存儲
- (三十)AngularJS項目開發技巧之圖片預加載
- (三十一)AngularJS項目開發技巧之獲取模態對話框中的組件ID
- (三十二)書海拾貝之特殊的ng-src和ng-href
- (三十三)書海拾貝之簡介AngularJS中使用factory和service的方法
- (三十四)Angular數據更新不及時問題探討
- (三十六)AngularJS項目開發技巧之利用Service&Promise&Resolve解決圖片預加載問題(后記)