如何处理嵌套的Dojo延迟

时间:2014-09-03 19:01:43

标签: javascript dojo esri arcgis-js-api

我希望根据识别任务的结果查询图层的任何附件。如果图层上有附件,我想将链接添加到infoTemplate的底部。

我在处理多个dojo Deferred对象时遇到问题。我知道他们正在解决,因为返回值记录在控制台中,但我的infoWindow从未填充。

那么处理几个嵌套延迟的正确方法是什么?延迟列表似乎是朝着正确方向迈出的一步,但我不确定在这种情况下我将如何格式化。

谢谢,

更新

我已在下面更新了我的工作代码。

map.on('click',executeIdentify);

function executeIdentify(evt) {
  identifyParams.width = map.width;
  identifyParams.height = map.height;
  identifyParams.geometry = evt.mapPoint;
  identifyParams.mapExtent = map.extent;

  var deferred = identifyTask.execute(identifyParams);

  deferred.addCallback(function(deferredResult){
    var promiseList = []
    var features = array.map(deferredResult,function(result) {

      var feature = result.feature;
      var content = "";
      array.forEach(Object.keys(feature.attributes),function(attr) {
        content += attr + ": " + feature.attributes[attr] + "<br>"
      });
      var url = identifyTask.url + "/" + result.layerId + "/" + result.feature.attributes.OBJECTID + "/attachments?f=json"
      var req = esriRequest({url:url}).then(function(newDef) {

        if (Object.keys(newDef).toString() == "attachmentInfos,_ssl") {
          content += "<br><b>Attachments:</b><hr>"
          array.forEach(newDef.attachmentInfos,function(attach) {
            content += "<a href=" + identifyTask.url + "/" + result.layerId + "/" + result.feature.attributes.OBJECTID + "/attachments/" + attach.id + " target='_blank'>" + attach.name + "</a><br>"
          })
        }
        content += "<br><br>";
        console.log(result)
        feature.infoTemplate = new InfoTemplate(result.layerName + " " + result.feature.attributes.OBJECTID,content)
        // console.log(feature)
        return feature
      },function(newDef) {
        feature.infoTemplate = new InfoTemplate(result.layerName + " " + result.feature.attributes.OBJECTID,content);
        // console.log(feature)
        return feature
      });
      promiseList.push(req);
    });
    var promiseAll = new all(promiseList)
    promiseAll.then(function(r) {promiseFun(r)})
  })
  function promiseFun(r) {
    map.infoWindow.setFeatures(r);
    map.infoWindow.show(evt.mapPoint);
  }
}

1 个答案:

答案 0 :(得分:3)

您应该考虑使用dojo/promise/all来处理多个延迟结果。这是一个使用它来返回多个服务的结果的示例,还有一些额外的代码来识别结果来自哪个服务。

    <!DOCTYPE html>  
<html>  
<head>  
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">  
    <!--The viewport meta tag is used to improve the presentation and behavior of the samples  
      on iOS devices-->  
    <meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no">  
    <title>Identify with Popup</title>  

    <link rel="stylesheet" href="http://js.arcgis.com/3.8/js/esri/css/esri.css">  
    <style>  
        html, body, #map {  
            height: 100%;  
            width: 100%;  
            margin: 0;  
            padding: 0;  
        }  
    </style>  

    <script>var dojoConfig = { parseOnLoad: true };</script>  
    <script src="http://js.arcgis.com/3.8/"></script>  
    <script>  

        var map;  
        var identifyTask, identifyParams, idPoint;  
        var identifyResults;  

        require([  
          "esri/map", "esri/dijit/Popup", "dojo/promise/all", "dojo/domReady!"  
        ], function (  
          Map, Popup, All  
        ) {  
            var popup = new Popup({  
                fillSymbol: new esri.symbol.SimpleFillSymbol(esri.symbol.SimpleFillSymbol.STYLE_SOLID, new esri.symbol.SimpleLineSymbol(esri.symbol.SimpleLineSymbol.STYLE_SOLID, new dojo.Color([255, 0, 0]), 2), new dojo.Color([255, 255, 0, 0.25]))  
            }, dojo.create("div"));  

            map = new Map("map", {  
                basemap: "satellite",  
                center: [-83.275, 42.573],  
                zoom: 18,  
                infoWindow: popup  
            });  

            dojo.connect(map, "onLoad", mapReady);  

            var landBaseLayer = new esri.layers.ArcGISDynamicMapServiceLayer("http://sampleserver3.arcgisonline.com/ArcGIS/rest/services/BloomfieldHillsMichigan/Parcels/MapServer", { opacity: .55 });  
            map.addLayer(landBaseLayer);  

            var militaryLayer = new esri.layers.ArcGISDynamicMapServiceLayer("http://sampleserver6.arcgisonline.com/arcgis/rest/services/Military/MapServer", { opacity: .55 });  
            map.addLayer(militaryLayer);  


            function mapReady(map) {  
                dojo.connect(map, "onClick", runIdentifies);  
            }  

            function runIdentifies(evt) {  
                identifyResults = [];  
                idPoint = evt.mapPoint;  
                var layers = dojo.map(map.layerIds, function (layerId) {  
                    return map.getLayer(layerId);  
                });  
                layers = dojo.filter(layers, function (layer) {  
                    if (layer.visibleLayers[0] !== -1) {  
                        return layer.getImageUrl && layer.visible  
                    }  
                }); //Only dynamic layers have the getImageUrl function. Filter so you only query visible dynamic layers  
                var tasks = dojo.map(layers, function (layer) {  
                    return new esri.tasks.IdentifyTask(layer.url);  
                }); //map each visible dynamic layer to a new identify task, using the layer url  
                var defTasks = dojo.map(tasks, function (task) {  
                    return new dojo.Deferred();  
                }); //map each identify task to a new dojo.Deferred  
                var params = createIdentifyParams(layers, evt);  

                var promises = [];  

                for (i = 0; i < tasks.length; i++) {  
                    promises.push(tasks[i].execute(params[i])); //Execute each task  
                }  

                var allPromises = new All(promises);  
                allPromises.then(function (r) { showIdentifyResults(r, tasks); });  
            }  

            function showIdentifyResults(r, tasks) {  
                var results = [];  
                var taskUrls = [];  
                r = dojo.filter(r, function (result) {  
                    return r[0];  
                });  
                for (i = 0; i < r.length; i++) {  
                    results = results.concat(r[i]);  
                    for (j = 0; j < r[i].length; j++) {  
                        taskUrls = taskUrls.concat(tasks[i].url);  
                    }  
                }  
                results = dojo.map(results, function (result, index) {  
                    var feature = result.feature;  
                    var layerName = result.layerName;  
                    var serviceUrl = taskUrls[index];  
                    feature.attributes.layerName = result.layerName;  

                    var template = new esri.InfoTemplate("", "Service Url: " + serviceUrl + "<br/><br/>Layer name: " + result.layerName + "<br/><br/> Object Id: ${OBJECTID}");  
                    feature.setInfoTemplate(template);  

                    var resultGeometry = feature.geometry;  
                    var resultType = resultGeometry.type;  
                    return feature;  
                });  

                if (results.length === 0) {  
                    map.infoWindow.clearFeatures();  
                } else {  
                    map.infoWindow.setFeatures(results);  
                }  
                map.infoWindow.show(idPoint);  
                return results;  
            }  

            function createIdentifyParams(layers, evt) {  
                var identifyParamsList = [];  
                identifyParamsList.length = 0;  
                dojo.forEach(layers, function (layer) {  
                    var idParams = new esri.tasks.IdentifyParameters();  
                    idParams.width = map.width;  
                    idParams.height = map.height;  
                    idParams.geometry = evt.mapPoint;  
                    idParams.mapExtent = map.extent;  
                    idParams.layerOption = esri.tasks.IdentifyParameters.LAYER_OPTION_VISIBLE;  
                    var visLayers = layer.visibleLayers;  
                    if (visLayers !== -1) {  
                        var subLayers = [];  
                        for (var i = 0; i < layer.layerInfos.length; i++) {  
                            if (layer.layerInfos[i].subLayerIds == null)  
                                subLayers.push(layer.layerInfos[i].id);  
                        }  
                        idParams.layerIds = subLayers;  
                    } else {  
                        idParams.layerIds = [];  
                    }  
                    idParams.tolerance = 3;  
                    idParams.returnGeometry = true;  
                    identifyParamsList.push(idParams);  
                });  
                return identifyParamsList;  
            }  

        });  
    </script>  
</head>  

<body>  
    <div id="map"></div>  
</body>  

</html>