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

时间:2015-12-11 21:41:34

标签: javascript callback dojo dijit.form arcgis-js-api

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

    从另一个模块调用
  1. publicMethodqueryNames
  2. 调用
  3. publicMethodexecute(parameters, callback?, errback?)
  4. 调用
  5. queryNames
  6. addNamesList被称为callback?
  7. execute参数
  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上看到更详细的解释和工作示例,我已将其放在代码审核中。

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

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

    修改

    使用此当前实现(使用dojo hitch),不会引发任何错误。方法addNamesList未被调用(也不是errback,我也不明白为什么)。我认为这是因为addNamesList不在map&#39; s(hitch first argument)命名空间。我试图改为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。这就是我试图使用故障的原因。

1 个答案:

答案 0 :(得分:3)

Javascript是异步的,因此来自db,http请求或通过回调返回的任何数据都非常多。以下是代码中发生的情况:

  • 公共方法调用queryNames
  • queryNames异步调用addNamesList的{​​{1}}并且不返回任何内容
  • 公共方法收回控制权,同时有些内容正在进行map
  • addNamesList在背景中仍有一些东西仍然没有被触及

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

query

所以,你应该做的就是将callback(mapLayer); 尽可能深地传递到你已准备好callback的地方(所以你已经完成了你想要的一切),然后执行mapLayer

Thisthis可能会更好地解释。

此致,亚历山大