无法理解javascript中嵌套事件中的闭包/范围

时间:2016-02-28 09:44:04

标签: javascript angularjs kml mapbox gpx

我正在以角度编写应用程序,并且必须确定是否可以将图层作为GPX或KML(地理数据XML文件)加载。然后我返回它成功加载的图层。但是,当我在.on(ready)事件(成功事件)中时,我不能为我的生活弄清楚如何将变量设置为true。这是我的代码:

(function() {
'use strict';

angular
    .module('TractNotes')
    .factory('xmldataService', xmldataService);

xmldataService.$inject = [];

/* @ngInject */
function xmldataService() {
    var isKML = false;
    var isGPX = false;

    var service = {
        getxmldata: getxmldata
    };
    return service;

    ////////////////

    function getxmldata(layer) {
        var kml = omnivore.gpx('this will fail')
            .on('ready', function() {
                isKML = true;
            })
            .on('error', function() {
                console.log("This is not a KML layer.")
            })

        var gpx = omnivore.gpx(layer)
            .on('ready', function() {
                isGPX = true;
            })
            .on('error', function() {
                console.log("This is not a GPX layer.")
            });

        if(isKML){
            return kml;
        }
        else if(isGPX){
            return gpx;
        }
        else{
            return 'invalid file';
        }
        // @TODO: use desc xml tag as layer name
    }
}
})();

当代码运行时,console.logs正常工作但它从不返回任何内容,因为布尔值从未正确设置。任何帮助理解这一点是值得赞赏的。

leaflet-omnivore docs:https://github.com/mapbox/leaflet-omnivore

1 个答案:

答案 0 :(得分:1)

嗯,那并不容易。当您运行服务功能时,准备好'事件还没有发生,因此bool值处于false状态。因此,他们会返回无效的文件'。我建议重构你的服务以返回Promise而不是value。看一下Promise on MDN。然后在承诺解决时执行您的代码。

<强> UPD:

此处,请查看jsfiddle

上的示例
function xmlDataService() {
  var service = {
    getxmlData: getxmlData
  };
  return service;

  function getxmlData(layer) {
    return new Promise(
      function(resolve, reject) {
        console.log('Promise started');
        var serviceCreated = false;
        var optionsCount = 2;
        var optionsFailed = 0;

        // First service
        window.setTimeout(
          function() {
            if (!serviceCreated) {
              serviceCreated = true;
              resolve('First service created');
            }
          }, Math.random() * 2000 + 1000); // at least a second

        // Second Service
        window.setTimeout(
          function() {
            if (!serviceCreated) {
              serviceCreated = true;
              resolve('Second service created');
            }
          }, Math.random() * 2000 + 1000);
      }
    );
  }
}

范围:

$scope.createService= function() {
  $scope.message = "Creating a Service";
  var promise = xmlDataService.getxmlData();
  promise.then(function(val) {
    console.log('Promise resolved');
    // Apply result on scope, since it been executed out of scope.
    $scope.$apply(function(){
      $scope.message = val;
    });
  });
}