Identify Task-How to combine results from two deferred object?

2048
2
08-05-2014 10:14 PM
GauriDeshmukh
New Contributor III

I m executing identify task on multiple services,thus getting results of all services, i want to combine all results to show in a infowindow.

map.on('click',function(event){

  var identify_result=[];

  var resultDef=[];

  var callback_counter=0;

  var deferred;

  var counter_res=0;

  map.setCursor("Default");

  if(viewData_clicked){

  var def = new dojo.Deferred();

  dojo.forEach(layerInfo,function(id){

  var url = map.getLayer(id).url;

  identifyTask = new IdentifyTask(url);

  identifyParams = new IdentifyParameters();

  identifyParams.tolerance=10;

  identifyParams.returnGeometry = true;

  identifyParams.layerIds = map.getLayer(id).visibleLayers;

  identifyParams.layerOption = IdentifyParameters.LAYER_OPTION_VISIBLE;

  identifyParams.width = map.width;

  identifyParams.height = map.height;

  identifyParams.geometry = event.mapPoint;

  identifyParams.mapExtent = map.extent;

  deferred = identifyTask

    //identifyTask

  .execute(identifyParams)

  .addCallback(function (response) {

  console.log("response",response);

  return arrayUtils.map(response, function (result) {

  var feature = result.feature;

  var layerName = result.layerName;

  // map.infoWindow.setTitle(layerName);

  var content = "<tr bgcolor='grey'><th><b>Field Name</b></th><th><b>Value</b></th></tr>";

  $.each(feature.attributes,function (key,value){

  content +="<tr><td>"+ key+"</td><td><b>"+value+"</b></td></tr>";

  });

  // map.infoWindow.setContent("<table border='1'>"+content+"</table>");

  var infotemplate = new InfoTemplate(layerName,"<table border='1'>"+content+"</table>");

  feature.setInfoTemplate(infotemplate);

  return feature;

  });

  });//execute

  callback_counter++;

  identify_result.push(deferred);

  }); //forEach

  //if(layerInfo.length === callback_counter){

  //var def = identifyTask.execute();

  var res_features=[];

  dojo.require("dojo.promise.all");

  dojo.forEach(identify_result,function(i){

  counter_res++;

  var def = dojo.promise.all()

  def.then(function(result) {

  //res=result;

  dojo.forEach(result,function(element){

  dojo.forEach(element,function(j){

  res_features.push(j);

  });

  });

  if((identify_result.length === counter_res) && (res_features.length > 0) ){

  console.log("identify_result.length",identify_result.length);

  console.log("counter_res",counter_res);

  console.log("result",result);

  console.log("res_features",res_features);

    var defrd = new dojo.Deferred();

  defrd = deferred;

  defrd.results=res_features;

    console.log(defrd);

  //map.infoWindow.setFeatures([defrd]);

  //map.infoWindow.show(event.mapPoint);

  }

  });

});

0 Kudos
2 Replies
KenBuja
MVP Esteemed Contributor

Here's an example that uses dojo/promise/all. This also contains extra code to identify which service the results are coming from

<!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.execute(params)); //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);

                    for (j = 0; j < r.length; j++) {

                        taskUrls = taskUrls.concat(tasks.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.subLayerIds == null)

                                subLayers.push(layer.layerInfos.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>

JoshHevenor
Occasional Contributor II

You can run each Identify individually and append their results to your infoWindow, so no need to synchronize. I haven't tested as a whole, key part on line 12:

function handleIdentify(/*IdentifyResult*/ results){

    var features = [];

    // deal with results, set up templates, etc.

    // . . .

    // populate features as required

    // Get the features currently in your infoWindow

    var existingFeatures = map.infoWindow.features || [];

    // Append the latest result set

    map.infoWindow.setFeatures(existingFeatures.concat(features));  // <-- key part

}

function handleErrror(err){

    // . . .

}

// Your many service URLs

var serviceUrls = [

    "http://service1/",

    "http://service2/",

    "http://service3/",

];

// for each URL

for(n in services){

    // create a new task

    var identify = new IdentifyTask(serviceUrls);

    // set the params as needed

    var identifyParams = new IdentifyParameters();

    // Execute the task   

    identify.execute(identifyParams, handleIdentify, handleError);

}

map.infoWindow.show(somePoint);