javascript – 在回调和事件后调用方法

我有一个模块,有四个函数,一个一个调用.我正在尝试遵循Revealing Module Pattern.其中一个功能是公共的,其余的是私人的.它是这样的:

>从另一个模块调用publicmethod
>从publicmethod调用queryNames
> query(参数,回调?,错误回复?)是从queryNames调用
> addNamesList被称为回调?执行的论点
>创建了几个dijit / form / CheckBox,并在onChange上触发方法querySegments
> querySegments需要调用在publicmethod中创建的对象的方法.

问题出在第6步,我无法到达步骤1中创建的对象.

我试过用dojo hitch来定义回调?第3步中的参数,但我不能让它工作.我尝试将它放在它的第一个参数中,但即便如此,我也无法达到调用addNamesList所需的范围.

以下是一些用于演示此问题的代码.

define([
  'dojo/dom',
  'dijit/form/CheckBox',
  'esri/layers/ArcGISDynamicMapServiceLayer',
  'esri/tasks/query',
  'esri/tasks/QueryTask',
  'dojo/_base/lang'
],
  function (
    dom,
    CheckBox,
    ArcGISDynamicMapServiceLayer,
    Query, QueryTask,
    lang
  ) {
    // ***************
    // private methods
    // ***************

    // fetch names and call addNamesList to put the list in place
    var queryNames = function (map, mapLayer) {
      // new QueryTask(url, options?)
      var queryTask = new QueryTask("url")
      var query = new Query()
      // execute(parameters, callback?, errback?)
      // this callback passes an argument called featureSet
      queryTask.execute(query, lang.hitch(map, "addNamesList", mapLayer), function(error) {console.log(error)})
    }  

    // callback function of queryNames
    var addNamesList = function (mapLayer, featureSet) {
      console.log('addOplist')
      var namesCount = featureSet.features.length
      for (var i = 0; i <namesCount; i++) {
        // work
        var cBox = new CheckBox({
          id: "cBox_" + i,
          value: featureSet.features[i].attributes["someID"],
          checked: false,
          onChange: function (evt) {
            querySegments(this.value, mapLayer)
          }
        })
        cBox.placeAt("someDiv" + i, "first")
      }
    }

    // triggered by the checkBox event
    var querySegments = function (name, mapLayer) {
        // build the query
        var queryStatement = "someID = " + name
        var layerDeFinitions = [queryStatement]
        // call a method of mapLayer
        mapLayer.setLayerDeFinitions(layerDeFinitions)
    }

    // **************
    // public methods
    // **************
    var publicmethod = function (map) {
      var mapLayer = new ArcGISDynamicMapServiceLayer('restURL')
      map.addLayer(mapServiceLayer)
      queryNames(map, mapLayer)
      return mapLayer
    }

    return {
      publicmethod: publicmethod
    }
  }
)

您可以在this other (and more broad) question上查看更详细的解释和工作示例,我已将其放在Code Review上.

我是JavaScript新手,我想我仍然有很多关于范围,闭包和回调的问题.

我将非常感谢任何意见,包括如何改进这个问题.

编辑

使用此当前实现(使用dojo hitch),不会引发任何错误.方法addNamesList没有被调用(也没有errback,我也不明白为什么).我认为这是因为addNamesList不在map(hitch first argument)命名空间中.我尝试用这个来代替,但没有区别.

在我决定使用hitch之前,代码看起来像这样:

var queryNames = function (map, mapLayer) {
  ...
  queryTask.execute(query, addNamesList)
}

var addNamesList = function (featureSet) {
  ...
    ...
      ...
        querySegments(this.value, mapLayer)
}

但后来我无法在复选框事件触发的方法内到达mapLayer.它会抛出Uncaught ReferenceError:mapLayer未定义.这就是我试图使用故障的原因.

解决方法:

Javascript是异步的,因此几乎所有来自db,http请求或通过回调返回的数据的数据.以下是您的代码中发生的情况:

> public方法调用queryNames
> queryNames异步调用map的addNamesList并且不返回任何内容
> public方法收回控制权,同时有些东西正在使用addNamesList
> mapLayer未经修改而返回,而某些内容仍在后台进行

因此,为避免这种情况,您应该通过回调从公共方法返回数据,因此您将回调作为第二个参数传递给public方法,然后传递给querySegments.然后,在成功回调查询时,当你最终得到结果时,你会做:

callback(mapLayer);

所以,你应该做的一切就是把这个回调尽可能深地传递到你准备好mapLayer的地方(所以你已经完成了你想要的一切),然后做一个回调(mapLayer);.

Thisthis可能会更好地解释.

此致,亚历山大

相关文章

我有一个网格,可以根据更大的树结构编辑小块数据.为了更容易...
我即将开始开发一款教育性的视频游戏.我已经决定以一种我可以...
我正在使用带有Grails2.3.9的Dojo1.9.DojoNumberTextBox小部...
1.引言鉴于个人需求的转变,本系列将记录自学arcgisapiforja...
我正在阅读使用dojo’sdeclare进行类创建的语法.描述令人困惑...
我的团队由更多的java人员和JavaScript经验丰富组成.我知道这...