Timeout Issues

4063
16
01-05-2016 11:43 AM
TomLeMahieu
New Contributor II

What I'm trying to do is zoom to the selected feature and then send the map to the printer.  Then zoom to the buffer and again print the resulting map to the printer.  Each of the following steps works by themselves.  However, I'm having a problem figuring out how to sequence the statements and use timeouts to ensure that each step is completed before the next process starts?  Here's my code:

//Zoom to Parcel                                 

setTimeout(lang.hitch(this, function () {

    this.zoomselected();

}), 3000);

setTimeout(lang.hitch(this, function () {

    html.setStyle(this.PrintMessage, 'display', 'block');

}), 5000);

            

//Zoom to Buffer

setTimeout(lang.hitch(this, function () {

    this.zoombuffer();

}), 3000);

setTimeout(lang.hitch(this, function () {

    html.setStyle(this.PrintMessage, 'display', 'block');

    this.sendToPrinter_SoilErosion(sTitle,sLayout,sFormat,sMessage);

}), 5000);

0 Kudos
16 Replies
GirishYadav
Occasional Contributor

Hey Tom,

I would suggest its better to use dojo Deffered to chain these functions rather than using timeouts.

Getting Started with Deferreds - Archived Tutorial - Dojo Toolkit

- Girish

ChrisSmith7
Frequent Contributor
TomLeMahieu
New Contributor II

Girish,

Thanks for your quick reply.  That makes a lot of sense.  I'll let you know how it goes.

Tom

0 Kudos
TomLeMahieu
New Contributor II

Girish and Chris,

I reviewed the samples using dojo deferred, but I'm still not sure how to make this work. I'm not very experienced in dojo, so I'm looking for a simple example using the ArcGIS JavaScript api.

I'm trying to execute the following two functions which work fine if I stop each of them using alert.

this.zoomselected();
this.sendToPrinter_SoilErosion(sTitle,sLayout,sFormat);

I tried all kinds of deferred statements like the following, but nothing seems to work.

var def = new Deferred();
def = this.zoomselected();               
def.then(function() {
    this.sendToPrinter_SoilErosion(sTitle,sLayout,sFormat);
});

Does anyone have any similar examples I can look at?

Thanks.

Tom

0 Kudos
GirishYadav
Occasional Contributor

Hey Tom,

Yeah, initially its a bit tricky to understand deferred and promise but once you get your hands dirty its very simple and cool. Most of the ESRI javascript API functions already return deferred where ever necessary. So its even easier to use it for ESRI javascript API. Here is an example to chain ajax calls using dojo deferred and promise. Dojo Deferred - Chaining - JSFiddle .

Its a very simple functionality to print map in two different scales.

here is a crux of it:

function printMap(){
    var printTask = new PrintTask("http://sampleserver6.arcgisonline.com/arcgis/rest/services/Utilities/PrintingTools/GPServer/Export%2...");
    var printTemplate = new PrintTemplate();
    printTemplate.layout = "MAP_ONLY"; //"A4 Portrait";
    printTemplate.preserveScale = false; 
    var params = new PrintParameters();
    params.map = this.map;
    params.template = printTemplate;
    dom.byId("printButtonNode").innerHTML = "Printing...";
    return printTask.execute(params);
  };
    
function zoomToSelectedFeatures(){    
    var selectedExt = map.extent;
    return map.setExtent(selectedExt);
};
    
function zoomToBufferedFeatures(){    
    var bufferedExt = map.extent.expand(1.5);
    return map.setExtent(bufferedExt);
};

function addResults(results){
    var resultContainer = dom.byId("results");
    domConstruct.place('<div><a href="' + results.url + '" target="_blank">Map </a></div>', resultContainer); 
    dom.byId("printButtonNode").innerHTML = "Print";
};

 on(dom.byId("printButtonNode"), "click", function(){  
    dom.byId("results").innerHTML = "";
    zoomToSelectedFeatures()
     .then(printMap)
     .then(addResults)
     .then(zoomToBufferedFeatures)
     .then(printMap)
     .then(addResults);     
   });
});

Thanks

-Girish

TomLeMahieu
New Contributor II

Girish,

That was super helpful and I think I'm getting close.  However, when I run zoombuffer first, it zooms to the buffer but when it tries to run the zoomselected function, it thinks that this.selValueShapeFeatures is undefined.  When I reverse the order, then zoomselected zooms to the selected feature, but when it tries to run the zoombuffer, it thinks that this.graphicsLayerBuffer is undefined.  What am I missing? Here's the simple code:

onTest: function () {

          

    this.zoombuffer()

                .then(this.zoomselected)

                .then(this.zoombuffer);

       

},

zoomselected: function () {

    if (this.selValueShapeFeatures) {

            var features = this.selValueShapeFeatures;

            if (features.length != 0) {

                var graphics = features; 

                var gExt = graphicsUtils.graphicsExtent(graphics);

                var selectedExt = gExt.expand(1.1);

                return this.map.setExtent(gExt.expand(1.1));

            } else {

                return null;

            }

        }

},

     

zoombuffer: function () {

    if (this.graphicsLayerBuffer) {

            if (this.graphicsLayerBuffer.graphics.length > 0) {

                var graphics = this.graphicsLayerBuffer.graphics;

                var gExt = graphicsUtils.graphicsExtent(graphics);

                var bufferExt = gExt.expand(1.1);

                return this.map.setExtent(bufferExt);

            }

        } else {

            return null;

        }

},

Thanks.

Tom

0 Kudos
GirishYadav
Occasional Contributor

You need to lang.hitch the calls to these functions to set the execution scope.

add "dojo/_base/lang" to the imports and

onTest: function () {

         

    this.zoombuffer()

                .then(lang.hitch(this, this.zoomselected))

                .then(lang.hitch(this, this.zoombuffer));     

},

-Girish

TomLeMahieu
New Contributor II

Girish,

OK almost there.  Nothing is erroring out, but I've got a couple odd things that happen.  On the positive, all of the functions get executed and 2 reports get printed entitled "Title 1" and Title 2" as specified.  On the negative, the map extent in the printout remains unchanged.  It is not affected by zoomselected or zoombuffer.  It doesn't seem like the map completely refreshes itself before it creates the print task.  Any thoughts?  Here's my code.

            this.zoomselected()
                .then(lang.hitch(this, this.sendToPrinter_SoilErosion("Title 1",sLayout,sFormat,sMessage)))
                .then(lang.hitch(this, this.zoombuffer))          
                .then(lang.hitch(this, this.sendToPrinter_SoilErosion("Title 2",sLayout,sFormat,sMessage)));              

Thanks for your help!

Tom

0 Kudos
TomLeMahieu
New Contributor II

I tried to follow Girish's example and I kept the code example as simple as possible (See below).  However, the map extent in the print layout doesn't get affected by the zoombuffer function.  I've tried everything, but I can't get it to work.  I must be missing something!!

  onTest: function () {      

        //This executes both but doesn't zoom to the same extent
        this.zoombufferTest()
               .then(lang.hitch(this, this.sendToPrinter_Test()));
          
  },

  zoombufferTest: function () {

    var bufferExt = this.map.extent.expand(4.0);
    return this.map.setExtent(bufferExt);
  
  },
  sendToPrinter_Test: function () {
  
    var sTitle = "Test";
    var sLayout = "WRC_Landscape";
    var sFormat = "PDF";
   

    //Get the user settings from the form
    this.printTask = new PrintTask(this.printTaskURL, this.printParams);
    var template = new PrintTemplate();
    template.label = sTitle;
    template.layout = sLayout;
    template.format = sFormat;
    template.preserveScale = false;
       
    this.printParams.map = this.map;
    this.printParams.template = template;
    return this.printTask.execute(this.printParams, this.printComplete, this.printError);
 

},

Map before running code:

Print layout (note zoom not reflected):

Map after running code (zoomed out 4x)

0 Kudos