0

I'm working on a geoprocessing web application. My application will provide users with a specific set of options, the user will provide some data, and then I will process the data on the server and finally return the results. If it matters, I am using the CMV http://docs.cmv.io/en/1.3.3/ as a framework and trying to build my own plugin, but I suspect my problems are more general JS problems. Here is a pseudocode sample (note that this is pseudocode and not my actual code, which is a mess at the moment):

initializeTool: function() {
     //here I am able to access my map object through this.map
     //and I need it for my output
     on(dom.byId("mybutton"), "click", processInput);
}
processInput: function() {
     //pull user data from webpage
     var userData, queries;
     //launch query for all data
     for(var i in userData){
         queries[i] = query(userData[i]);
     }
     //deferredlist is from Dojo, doc here: http://dojotoolkit.org/api/?qs=1.10/dojo/DeferredList
     new DeferredList(queries).then(function (results) {
          //iterate over query responses and perform work
          for(var i in queries){
              //peform some synchronus operations
          }
          //and now we're done! but how do I get to my output?
     }
}

The desired output in this case is a group of objects that have had various operations done on them, but are only accessible in the scope of the then() block and the inline function. My problem is that the output I am trying to use is only in the scope of the initialize function. I'm not sure what the best way to get my processed data to where I want it to be. This is a problem because the processed data is geometry information - it isn't very human readable as text, so it needs to be displayed on a map.

I've been pouring over JS scoping and looking at references to try and figure out what my issue is, but I seriously cannot figure it out.

two bugs
  • 103
  • 1
  • 6
  • What "outputs" are you talking about. It's unclear what it is you want to achieve and where the problem lies. – Felix Kling Mar 27 '15 at 20:25
  • My output in this case is the transformed data. It's only available in the scope of the .then() block, but I'm just having a big brain fart on how to handle this situation in a good way. – two bugs Mar 27 '15 at 20:26
  • *"It's only available in the scope of the .then() block"* What's the problem about that? Where else do you want to have access to the data? – Felix Kling Mar 27 '15 at 20:28
  • 1
    Your code has serious syntax errors - JS doesn't have a `foreach` construct and you certainly can't `then` it - what are you calling `then` on? – Benjamin Gruenbaum Mar 27 '15 at 22:32
  • Maybe read [this question and answers](http://stackoverflow.com/questions/28250680/how-do-i-access-previous-promise-results-in-a-then-chain)? – Benjamin Gruenbaum Mar 27 '15 at 22:32
  • I was intending that code to be pseudocode and not indicative of my actual syntax... sorry if that was unclear. My actual code uses proper javascript syntax and runs without issue. I'll update the answer with some clarifications. – two bugs Mar 28 '15 at 00:46
  • @originaluser what's a DeferredList? – Benjamin Gruenbaum Mar 28 '15 at 10:51
  • Are you sure that you don't want to iterate the `results` (not the queries) in the `then` callback? – Bergi Mar 28 '15 at 13:15
  • @BenjaminGruenbaum Sorry about that, I'm using Dojo which I should have made clear earlier. Here is the doc for deferred lists: http://dojotoolkit.org/api/?qs=1.10/dojo/DeferredList They seem to be the right tool for the job, but it's entirely possible I'm misusing them. – two bugs Mar 28 '15 at 22:46

1 Answers1

1

One of the main points of promises is that then returns a promise for whatever is eventually returned inside its onFulfill handler. This is what enables you to get the outcome out of your processInput() function and into the world outside it.

So you can (and should) do this:

function processInput() {
     //pull user data from webpage
     var userData;

     //launch query for all data
     return Promise.all(userData.map(query))
     .then(function (results) {
          var theResult;
          //iterate over query responses and perform work
          results.forEach(function (result) {
              //peform some synchronus operations and determine theResult
          });
          return theResult;
     });
}

processInput().then(function (theResult) {
    // do something with theResult
});
JLRishe
  • 99,490
  • 19
  • 131
  • 169
  • 1
    I'm still wondering what the `foreach` syntax is and how that could possibly work? Is it supposed to be the ES6 `for (variable of object)` or the deprecated `for each`? – jfriend00 Mar 28 '15 at 17:25
  • @jfriend00 OP has clarified that it was pseudocode and has now replaced it with a `for..in`. I have replaced it with `results.forEach`. – JLRishe Mar 29 '15 at 06:23
  • Thank you for this answer, @JLRishe. It doesn't appear to be exactly what I am looking for (probably due to a poor explanation on my part), but this is helpful information about Javascript promise best-practices, so I have +1'd it. Or rather, I would, but I still lack the rep to do so :) – two bugs Mar 30 '15 at 14:09
  • @originaluser I'm pretty sure that I am giving you the answer that you are looking for and you just don't realize it yet. :) If you can point out which part doesn't seem to fit with what you are trying to do, I can clarify, so please tell me. – JLRishe Mar 30 '15 at 14:45
  • @JLRishe You were right! After dealing with an error on my backend server this approach has solved the problem. A valuable lesson in promise usage. Thank you very much, and thanks to the others who commented as well. – two bugs Mar 30 '15 at 15:46