在回调和事件之后调用方法

Call a method after a callback and an event

我有一个包含四个函数的模块,它们一个接一个地调用。我正在尝试遵循 Revealing Module Pattern。其中一个函数是public,其余都是私有的。它是这样的:

  1. publicMethod 被另一个模块调用
  2. queryNamespublicMethod
  3. 调用
  4. execute(parameters, callback?, errback?)queryNames
  5. 调用
  6. addNamesList 被称为 execute
  7. callback? 参数
  8. 创建了多个 dijit/form/CheckBox 并触发了方法 querySegments onChange
  9. querySegments 需要调用在 publicMethod.
  10. 中创建的对象的方法

问题出在第6步,无法访问第1步创建的对象

我尝试在第 3 步中使用 dojo hitch 定义 callback? 参数,但我无法让它工作。我尝试将 this 放在它的第一个参数中,但即使那样我也无法达到调用 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 的(第一个参数)命名空间中。我试着用 this 代替,但没有任何区别。

在我决定使用 hitch 之前,代码如下所示:

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

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

但后来我无法在复选框事件触发的方法中到达 mapLayer。它会抛出 Uncaught ReferenceError: mapLayer is not defined。这就是我尝试使用挂钩的原因。

Javascript 是异步的,因此几乎所有数据都来自数据库、http 请求或通过 回调 编辑的任何内容。以下是您的代码中发生的情况:

  • public 方法调用 queryNames
  • queryNames 异步调用 mapaddNamesList,并且 return 什么都没有
  • public 方法收回控制权,同时 addNamesList
  • 正在处理一些事情
  • mapLayer return 未受影响,但某些内容仍在后台运行

所以,为了避免这种情况,你应该通过回调从 public 方法中 return 数据,所以你将 callback 作为第二个参数传递给 public 方法,然后到querySegments。然后,在 query 的成功回调中,当你最终准备好结果时,你做:

callback(mapLayer);

因此,您应该做的就是将此 callback 尽可能深地传递到您准备好 mapLayer 的地方(因此您已经完成了您想要的一切),然后做一个 callback(mapLayer);.

This and this 可能会解释得更好。

最好的问候,亚历山大