AngularJS中的链接承诺/要求

时间:2016-02-23 07:57:40

标签: javascript angularjs promise

我的目标:

构建一个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。

我做错了什么?

2 个答案:

答案 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
});