Javascript AMD模式中的范围

时间:2013-05-09 17:43:50

标签: javascript jquery google-maps-api-3 requirejs amd

我是Java的Javascript新手,我不得不直接为我开始最困难的事情......使用异步模块定义模式开发应用程序......

我正在使用平台Weejot,该平台提供framework来开发使用AMD pattern的JavaScript网络应用。所有文档here。你可能不知道它,但如果你知道AMD模式,也许你可以帮忙......

基本上我有一个模块MyController.js看起来像这样(注意大部分代码是自动生成的,我只写了注释行):

define([
    "js/util",
    "framework/Controller"
], function (
  util,
  Controller
){      
  function MyController(environment, connector) {
    Controller.call(this, environment);
    this.settings = environment.siteApplication.getSettings();
    this.connector = connector;        
    //Variable where I have some value stored
    this.myVariable = "hello";
  }    

  MyController.prototype = Object.create(Controller.prototype);

  util.extend(MyController.prototype, {
    //Function to show a map
    showMap: function (request, render) {
      //Get google maps script
      $.getScript("http://maps.googleapis.com/maps/api/js?key=KEY&sensor=false");          
      //Render is a framework object that basically shows the view "map.html" in full page mode
      render({name: "map", mode: "fullPage"});
    }    
  });

  return MyController;
});

这不能正常工作,因为在$.getScript(...)行之后,似乎没有加载脚本,因为我无法访问应该创建的对象google.maps ...

我通过向脚本url添加回调函数来实现它,如下所示:

$.getScript("http://maps.googleapis.com/maps/api/js?key=KEY&sensor=false&callback=drawMap");

问题是这个回调函数必须是全局函数,所以我将以下函数添加到上一个模块(就在上面的return语句之前):

window.drawMap = function () {
  var mapOptions = {
    center: new google.maps.LatLng(-34.397, 150.644);,
    zoom: 8,
    mapTypeId: google.maps.MapTypeId.ROADMAP
  };
  var map = new google.maps.Map(document.getElementById("map_canvas"), mapOptions);
}

不知怎的,我把地图渲染得很完美......但是,我的问题是我需要从函数myVariable访问变量window.drawMap,我不能......有什么办法吗?或者我从一开始就做错了什么?

正如我所说的那样,我对这一切都是新手,而且我变得疯狂,并且在努力使其发挥作用时,我一直在添加和改变事物,以至于我不知道我到底在做什么做...任何建议将不胜感激......


编辑:如果它有用,这是获取Google地图脚本时的响应(从Chrome控制台复制):

window.google = window.google || {};
google.maps = google.maps || {};
(function() {

  function getScript(src) {
    var s = document.createElement('script');

    s.src = src;
    document.body.appendChild(s);
  }

  var modules = google.maps.modules = {};
  google.maps.__gjsload__ = function(name, text) {
    modules[name] = text;
  };

  google.maps.Load = function(apiLoad) {
    delete google.maps.Load;
    apiLoad([0.009999999776482582,[[["http://mt0.googleapis.com/vt?lyrs=m@216000000\u0026src=api\u0026hl=es-ES\u0026","http://mt1.googleapis.com/vt?lyrs=m@216000000\u0026src=api\u0026hl=es-ES\u0026"],null,null,null,null,"m@216000000"],[["http://khm0.googleapis.com/kh?v=128\u0026hl=es-ES\u0026","http://khm1.googleapis.com/kh?v=128\u0026hl=es-ES\u0026"],null,null,null,1,"128"],[["http://mt0.googleapis.com/vt?lyrs=h@216000000\u0026src=api\u0026hl=es-ES\u0026","http://mt1.googleapis.com/vt?lyrs=h@216000000\u0026src=api\u0026hl=es-ES\u0026"],null,null,"imgtp=png32\u0026",null,"h@216000000"],[["http://mt0.googleapis.com/vt?lyrs=t@131,r@216000000\u0026src=api\u0026hl=es-ES\u0026","http://mt1.googleapis.com/vt?lyrs=t@131,r@216000000\u0026src=api\u0026hl=es-ES\u0026"],null,null,null,null,"t@131,r@216000000"],null,null,[["http://cbk0.googleapis.com/cbk?","http://cbk1.googleapis.com/cbk?"]],[["http://khm0.googleapis.com/kh?v=75\u0026hl=es-ES\u0026","http://khm1.googleapis.com/kh?v=75\u0026hl=es-ES\u0026"],null,null,null,null,"75"],[["http://mt0.googleapis.com/mapslt?hl=es-ES\u0026","http://mt1.googleapis.com/mapslt?hl=es-ES\u0026"]],[["http://mt0.googleapis.com/mapslt/ft?hl=es-ES\u0026","http://mt1.googleapis.com/mapslt/ft?hl=es-ES\u0026"]],[["http://mt0.googleapis.com/vt?hl=es-ES\u0026","http://mt1.googleapis.com/vt?hl=es-ES\u0026"]],[["http://mt0.googleapis.com/mapslt/loom?hl=es-ES\u0026","http://mt1.googleapis.com/mapslt/loom?hl=es-ES\u0026"]],[["https://mts0.googleapis.com/mapslt?hl=es-ES\u0026","https://mts1.googleapis.com/mapslt?hl=es-ES\u0026"]],[["https://mts0.googleapis.com/mapslt/ft?hl=es-ES\u0026","https://mts1.googleapis.com/mapslt/ft?hl=es-ES\u0026"]]],["es-ES","US",null,0,null,null,"http://maps.gstatic.com/mapfiles/","http://csi.gstatic.com","https://maps.googleapis.com","http://maps.googleapis.com"],["http://maps.gstatic.com/intl/es_es/mapfiles/api-3/12/11","3.12.11"],[2244818506],1.0,null,null,null,null,0,"blabla",null,null,0,"http://khm.googleapis.com/mz?v=128\u0026","AIzaSyAgUZ1LkdjZ9jsRivdSB4cDLmUAOMOMi34","https://earthbuilder.googleapis.com","https://earthbuilder.googleapis.com",null,"http://mt.googleapis.com/vt/icon"], loadScriptTime);
  };
  var loadScriptTime = (new Date).getTime();
  getScript("http://maps.gstatic.com/intl/es_es/mapfiles/api-3/12/11/main.js");
})();

1 个答案:

答案 0 :(得分:1)

编辑:我查看了脚本,而不是jsonp,所以我修改了我的答案以使用requirejs。

再次编辑:看来这里还有更多的非同步爵士乐。另一个将全局函数绑定到模块范围的编辑。

查看该URL返回的代码,似乎在代码中它进行另一次异步调用以从api检索其他数据,然后调用您的回调。我能想到的唯一方法是在模块中定义一个全局函数,并使用它来处理api调用的返回值。它不漂亮,但它应该工作:

define([
    "js/util",
    "framework/Controller"
], function (
  util,
  Controller
){      
  function MyController(environment, connector) {
    Controller.call(this, environment);
    this.settings = environment.siteApplication.getSettings();
    this.connector = connector;        
    //Variable where I have some value stored
    this.myVariable = "hello";
  }    

  MyController.prototype = Object.create(Controller.prototype);

  util.extend(MyController.prototype, {
    //Function to show a map
    createRenderer : function(){
       var self = this;
       window.drawMap = function(){
          var mapOptions = {
          center: new google.maps.LatLng(-34.397, 150.644);,
          zoom: 8,
          mapTypeId: google.maps.MapTypeId.ROADMAP
        };
        var map = new google.maps.Map(document.getElementById("map_canvas"), mapOptions);
        // Do stuff with self.myVariable and, render, ect...
      };
    },
    showMap: function (request, render) {
      //Get google maps script
      this.createRenderer();
      $.getScript("http://maps.googleapis.com/maps/api/js?key=KEY&sensor=false&callback=drawMap");                     }    
  });

  return MyController;
});

说明:

当您调用this.createRenderer()时,将在对象的上下文中调用该函数。由于我们在self = this函数调用中声明了一个变量this.createRenderer(),然后在该函数调用中定义window.drawMap,我们创建一个闭包,它将自引用存储到{{ 1}}对象。稍后调用MyController时,关闭范围中可以使用window.drawMap引用。现在,在self函数调用中,我们可以访问window.drawMap。有关详细信息,请参阅How do JavaScript closures work?

作为替代方案,您可以考虑使用Miller Medeiros的async plugin加载Google Maps api作为您模块的依赖项。这将是一种更清洁的方式。