我的目标:
构建一个AngularJS服务(MapService
),初始化(MapService.initMap()
)第三方控件(Esri ArcGIS Map)并返回对我的地图(MapService.getMap()
)的引用,以便我可以使用它在我的所有控制器中。
代码
<!DOCTYPE html>
<html ng-app="app">
<body ng-controller="MapController">
<script data-require="angular.js@1.5.0" data-semver="1.5.0" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.0/angular.js"></script>
<script defer type="text/javascript" src="//js.arcgis.com/4.0beta3/"></script>
<script src="angular-esri-loader.js"></script>
<script src="script.js"></script>
</body>
</html>
的script.js:
(function(angular) {
'use strict';
var app = angular.module('app', ['esri.core']);
angular.module('app')
.controller('MapController', function(esriLoader, $scope, MapService) {
MapService.getMap().then(function (mapObj) {
console.log("resolved!!!"); // this code is never reached
alert('show map');
$scope.map = mapObj;
});
MapService.initMap();
});
angular.module('app')
.service('MapService', function($q, esriLoader) {
this.deferred = $q.defer();
this.getMap = function(){
return this.deferred.promise;
}
var self = this;
this.initMap = function() {
// self.deferred.resolve('test'); // When I uncomment this line, the promise will be successfully resolved and the 'then' runs
esriLoader.require([
'esri/Map',
'esri/widgets/Search',
'esri/widgets/Search/SearchViewModel'
]).then(function(esriModules){
var Map = esriModules[0];
var Search = esriModules[1];
var SearchViewModel = esriModules[2];
// Create the map
var map = new Map({
basemap: 'satellite'
});
console.log("resolve map"); // this code is reached, however, it still doesn't seem to correctly resolve the promise
self.deferred.resolve(map);
});
}
});
})(angular);
Plunkr
https://plnkr.co/edit/LEhYqHVSpscTZ5kJCfyJ
问题:
getMap()
返回的承诺永远不会被解决,因此MapService.getMap().then()
中的代码永远不会到达。
当我使用self.deferred.resolve('test');
方法中的某个测试字符串(initMap()
)解析承诺时,它可以正常工作。
所以我认为这是'esriLoader.require()'方法的问题,这是在require
地图组件的某些依赖关系之后解决的另一个承诺。
所以我基本上是在承诺中解决承诺。我将esriLoader的代码添加到了plunkr。
我做错了什么?
答案 0 :(得分:1)
问题是Map
实现了某种承诺接口。我建议查看文档。您可以通过将地图包装到对象中来解决您的问题:
var map = {
map: new Map({
basemap: 'satellite'
})
};
console.log("resolve map"); // this code is reached
self.deferred.resolve(map);
正如其他人已经建议的那样,最好是调用MapService.initMap().then
而不是调用这两种方法并创建自己的承诺。您可以返回(包装)地图而不是使用地图解析它:
this.initMap = function() {
//self.deferred.resolve('test'); // When I uncomment this line, the promise will be successfully resolved and the 'then' runs
return esriLoader.require([
'esri/Map',
'esri/widgets/Search',
'esri/widgets/Search/SearchViewModel'
]).then(function(esriModules){
var Map = esriModules[0];
var Search = esriModules[1];
var SearchViewModel = esriModules[2];
// Create the map
var map = new Map({
basemap: 'satellite'
});
console.log("resolve map"); // this code is reached
return {map: map};
});
答案 1 :(得分:-2)
尝试这种方式:
angular.module('app')
.service('MapService', function($q, esriLoader) {
var map;
this.initMap = function() {
// return map instance if it's already initialized
if (map) {
return $q.resolve(map);
}
var defered = $q.defer();
esriLoader.require([
'esri/Map',
'esri/widgets/Search',
'esri/widgets/Search/SearchViewModel'
]).then(function(esriModules){
var Map = esriModules[0];
var Search = esriModules[1];
var SearchViewModel = esriModules[2];
// Create the map
var map_ = new Map({
basemap: 'satellite'
});
map = map_;
defered.resolve(map_);
});
return defered.promise;
}
});
在需要地图实例时使用initMap
:)
MapService.initMap().then(function (map) {
// use map here
});