无法理解 javascript 中嵌套事件中的 closures/scope

Trouble understanding closures/scope in nested events in javascript

我正在 angular 中编写应用程序,必须确定图层是否可以加载为 GPX 或 KML(地理数据 XML 文件)。然后我 return 它被成功加载的图层。但是,当我在 .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 工作正常,但它从来没有 return 任何东西,因为布尔值从未被正确设置。感谢任何帮助理解这一点。

leaflet-omnivore 文档:https://github.com/mapbox/leaflet-omnivore

嗯,这并不容易。当您 运行 您的服务功能时, 'ready' 事件尚未触发,因此 bool 值处于 false 状态。所以他们 return 'invalid file'。我建议将您的服务重构为 return Promise 而不是价值。看看那个 Promise on MDN。然后在 promise 解决后执行你的代码。

更新:

在这里,看一下 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;
    });
  });
}