2

I have a map built in the Esri Javascript API.

This map has one layer within it, showing petrol stations.

As the extent of the map changes, I am running 4 separate queries against this layer to find out a count of the total petrol stations within the current extent, a query for each petrol station vendor.

e.g. (Somehat simplified)

//Shell 
shellQuery.where = "brand = 'Shell"
//Execute Query, and report result to console
shellQueryTask.executeForCount(shellQuery , function(count){
console.log(count);}

//BP
same again.  Repeats for 4 queries.

The results of each query are dojo.deferred.

However, as they are separate queries (needs to be this way for other reasons), they all return there results at slightly different times.

Final Goal - include a Dojo bar chart, that gets updated by these queries, to show a breakdown of the petrol stations in the current extent, based on vendor.

Being new to Javascript, let alone Dojo, I am scratching my head on the best way to update a dojo chart. Most the Esri samples I see are around displaying the results of one query, and do so by creating a new chart everytime.

I am looking for an answer that is the most elegant way of doing this.

Im currently thinking that I need to write the results of the 4 queries to a global data array and then call a separate function to update the dojo chart. Just a little concerned on ensuring that I dont call the function until all four queries have returned their results.

4

1 に答える 1

2

Dojo's deferreds and promises are great for this! In particular, the dojo/promise/all module (formerly DeferredList).

Since you say your executeForCount function returns Deferreds, you can do something like this:

shellQueryDeferred  = shellQueryTask.executeForCount(shellQuery);
texacoQueryDeferred = texacoQueryTask.executeForCount(texacoQuery);
....

// I assume you've required "dojo/promise/all" as "promiseAll" here:
promiseAll([shellQueryDeferred, texacoQueryDeferred, ...]).then(
    function(results) {
        // The "results" variable is an array with the results
        // from each query, after they've all completed.
    });

As for updating the chart, I'm not entirely sure what the most elegant way is. One thing to keep in mind is that chart.addSeries("name", [1,2,4]) can be called over and over with the same name, and the data for that series will simply be updated. You have to call chart.render() afterwards.

So for example:

promiseAll([shellQueryDeferred, texacoQueryDeferred, ...]).then(
    function(results) {
        var chartNumbers = getNumbersForChartFromQueryResults(results);
        chart.addSeries("Petrol stations", chartNumbers);
        chart.render();
    });

I always end up fiddling when making an answer, so perhaps it is of some help: http://fiddle.jshell.net/froden/SZmkJ/

Edit: Dojo 1.7 variant:

Like Juffy says, in 1.7, you have to use dojo/DeferredList. It's almost as simple as a search&replace, but there are a few gotchas. Firstly, it has to be instantiated like a class:

//promiseAll([shellQuery, texacoQuery, bobsPetrolAndBurgersQuery])
// I assume you've required "dojo/DeferredList" as "DeferredList" here:
new DeferredList([shellQuery, texacoQuery, bobsPetrolAndBurgersQuery])
    .then(function(data) { 
        ....

Secondly, the data in the callback function is now an array of arrays, where the first item in each sub-array is a success/failure boolean. So you probably have to massage the data a little before passing it to the chart. ( http://fiddle.jshell.net/froden/SZmkJ/1/ )

于 2012-12-09T14:14:33.933 に答える