-3

I have an ESRI 3.46 JavaScript application. There are a couple of functions which return data from an API. I am looping through the results and creating an array to be returned to other areas of my application. The problem I am having is the function is returning "undefined" instead of the array. If I send the results to the console before the return statement, the data is there. I am also using a little PHP in this.

 function requestDomains(layer){ var dUrl = '<?php echo $emapFS; ?>/queryDomains'; var domainRequest = new Request({ "url" : dUrl, "content": { "f": "json", "layers": '['+layer+']', }, async: false }); //domainRequest.then(domainParse, requestFailed); domainRequest.then(function(response){ var domains = response.domains var arr = []; //console.log(domains); jQuery.each(domains, function(key, value){ var dname = value.name; arr[dname] = []; var cValues = value.codedValues; jQuery.each(cValues, function(k, v){ var dcode = v.code.toString(); var dvalue = v.name.toString(); arr[dname][dcode] = dvalue; }); }); console.log(arr); //<------------ This returns the array in console. Looks good return arr; }); } function MainTabContent (results){ var template = ""; var wfeatures = results.features[0]; //console.log("Main"); var MainArray = <?php echo $mainFields; ?>; var layerid = mapLayers['Main Lines']; //console.log(layerid); var cDomains = requestDomains(layerid); console.log(cDomains); // <-----------------------This returns undefined template = "<i>Total features returned: " + wfeatures.length + "</i>"; template += "<table border='1' style='width:1000px;'>"; template += "<tr>" jQuery.each(MainArray, function(tkey, tvalue){ template += "<th>"+tvalue+"</th>" }); //template += "<th>Data</th>" template += "</tr>"; for (var i = 0, il = wfeatures.length; i < il; i++) { template += "<tr>"; jQuery.each(MainArray, function(key, value){ switch(key) { case "<?php echo $switchFields[4]; ?>": template += '<td width="300">'+ wfeatures[i].attributes[key] +'</td>'; break; case "<?php echo $switchFields[3]; ?>": template += '<td width="100">'+ wfeatures[i].attributes['DIAMETER'] +' '+ wfeatures[i].attributes['MATERIAL'] + '<a href="#" onclick="showFeature(mainResults.features[0]['+ i +']); return false;">(show)</a></td>'; break; case "<?php echo $switchFields[5]; ?>": asbuilt = wfeatures[i].attributes[key]; //console.log(asbuilt); if(asbuilt != 'Null') { template += '<td><a href="<?php echo base_url(); ?>gis/ab/' + asbuilt + '" target="_blank">' + asbuilt + '</a></td>'; } else { template += '<td>&nbsp;</td>'; } break; case "<?php echo $switchFields[0]; ?>": unitid = wfeatures[i].attributes[key]; template += "<td>"+ wfeatures[i].attributes[key] +"</td>"; break; case "<?php echo $switchFields[1]; ?>": unitid2 = wfeatures[i].attributes[key]; template += "<td>"+ wfeatures[i].attributes[key] +"</td>"; break; case "<?php echo $switchFields[6]; ?>": facilityID = wfeatures[i].attributes[key]; template += '<td><div class="csspointer" style="color:blue;text-decoration:underline;" onClick="window.open(\'/gis/HansenQuery/'+facilityID+'/COMPWMN\', \'\', \'width=400,height=400,menubar=no,scrollbars=yes\')">Asset Data</div></td>'; break; case "<?php echo $switchFields[7]; ?>": mLength = parseFloat(wfeatures[i].attributes[key]); template += "<td>"+ Math.round(mLength) +"</td>"; break; default: template += "<td>"+ wfeatures[i].attributes[key] +"</td>"; } }); //template += '<td><div class="csspointer" style="color:blue;text-decoration:underline;" onClick="window.open(\'/gis/HansenQuery/'+unitid+'/COMPWMN/'+unitid2+'\', \'\', \'width=400,height=400,menubar=no,scrollbars=yes\')">Hansen</div></td>'; template += "</tr>"; } template += "</table>"; return template; } 

The above code was shortened a bit. I initially had the request for the data in one function and the parsing of the data into an array in another.

1
  • 1
    return arr; is within a callback function which is executed when a domain request completes (this is an asynchronous process with a Promise). It's not a return statement for the requestDomains function. So that return value just gets returned to whatever code in the Request class triggered the callback...and it probably does nothing with it. Also since that request call is asynchronous, that doesn't happen until after the requestDomains function has already completed and returned, anyway. See the duplicate question above for more info and potential solutions.
    – ADyson
    CommentedApr 16 at 15:32

1 Answer 1

2

Seems you are in process of learning promises/async JS, please learn more: https://developer.mozilla.org/en-US/docs/Learn_web_development/Extensions/Async_JS/Promises

To fix your problem you should:

  1. Return your promise from requestDomains:
return domainRequest.then(function(response){ 
  1. Wait for the returned value:
requestDomains(layerid).then(cDomains =>{ // do the rest here }); 

Also I would recommend using async/await even with legacy code, that would potentially limit number of bugs associated with then() nested callback hell and problems like yours, improves readability greatly:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/await

async function MainTabContent (results){ ... var cDomains = await requestDomains(layerid); 

    Start asking to get answers

    Find the answer to your question by asking.

    Ask question

    Explore related questions

    See similar questions with these tags.