Select to view content in your preferred language

How to stop queryTask execution?

2084
13
Jump to solution
11-21-2012 03:32 AM
YvanBérard
Regular Contributor
Hi all,

i've created my own identify tool with the queryTask, but i can't find a way to stop the execution of the queryTask.

Is there a way to stop the execution?

Thanks.

function identificationTool(action,qryUE,queryTaskUE) {  alert(action);  if(action =="go")  {   dojo.connect(map, "onClick", function(evt)    {    console.log("Identification: click");           //onClick event returns the evt point where the user clicked on the map.          //This is contains the mapPoint (esri.geometry.point) and the screenPoint (pixel xy where the user clicked).          //set query geometry = to evt.mapPoint Geometry          qryUE.geometry = evt.mapPoint;           //Execute task and call showResults on completion          queryTaskUE.execute(qryUE, showResults);             });  }  else  {   dojo.connect(map, "onClick", function(evt)    {                         // Here we should stop the execution of the queryTaskUE    map.infoWindow.hide();   });  } }
0 Kudos
1 Solution

Accepted Solutions
YvanBérard
Regular Contributor
YES!!!

Finally!

It's working like "ArcMap"!!

here is my code if somebody need it.

function init() {         ...          $(document).ready(function()   {   toolAction(map,qryUE,queryTaskUE);  }); }  function toolAction(map,qryUE,queryTaskUE) {        ...     $("#identify_spot").bind("click", function(event)    {     // If it's the same tool   if( getActiveTool() == "#identify_spot" )   {    setActiveTool();                         // Clear all the graphics, but not the infoTemplate and I don't know why.    map.graphics.clear();    dojo.disconnect(getDojoClick());   }   // If it's the not same tool   else   {    setActiveTool("#identify_spot");    setDojoClick(dojo.connect(map, "onClick", function(evt)       {      identificationTool(qryUE,queryTaskUE,evt);      console.log("identification click");     })    );   }  }); }  var thisTool; var dojoAction;  function setActiveTool(tool) {  if(tool != null)  {   thisTool = tool;   $(thisTool).addClass("active_tool");   }  else  {   $(thisTool).removeClass("active_tool");   thisTool = "";   }  console.log(thisTool+" class=active_tool")  }  function getActiveTool() {  return thisTool; }  function setDojoClick(action) {  if( action != null )  {   dojoAction = action;  }  else  {   dojoAction = "vide";  } }  function getDojoClick() {  console.log("kill");  return dojoAction; }

View solution in original post

0 Kudos
13 Replies
YvanBérard
Regular Contributor
I've tried it with your idea (queryDeferred) but it doesn't seem to work.

When i call the function cancelExecute() it seems that the object queryDeferred is empty...but it's not supposed to. The queryDeferred is a global var. So why is it still empty and not working?

function identificationTool(action,qryUE,queryTaskUE)
{
 console.log("identification? "+action)
 if(action == true )
 {
  dojo.connect(map, "onClick", function(evt) 
  {
   console.log("Identification: click");   
                 qryUE.geometry = evt.mapPoint;
                 queryDeferred = queryTaskUE.execute(qryUE);
                 queryDeferred.then(showResults,showError);
                 });
 }
 
 if(action == false)
 {
  cancelExecute();
 }
}

function cancelExecute() 
{
 console.log("identification queryDeferred("+queryDeferred+") to stop = "+queryDeferred.fired)
 if(queryDeferred && (queryDeferred.fired > 0)) 
 {
  console.log("Identification: stop");
  queryDeferred.cancel();
 }
}

0 Kudos
__Rich_
Deactivated User
It is either out of scope or uninitialised.

Looking at your code, it looks like there's a path through identificationTool where cancelExecute could be called before queryDeferred has been set.

Have you got the rest of the code available?

I've had a 5 minute play with this, here's a snippet:

var def = queryTask.execute(query,
    function (featureSet) {
        alert("FeatureSet returned");
    },
    function (err) {
        alert("Error...but can't get at the message/reason that you expected to see, unfortunately.\n\ndef.canceled (sic) = " + def.canceled);
    }
);
def.cancel("A reason for cancelling can be provided here",/*not strict*/false);


This won't cancel the server-side processing (if that's what you're hoping for) but it does cancel the client-side processing of any results...but not in the way that the Dojo people intended, it would seem.
0 Kudos
YvanBérard
Regular Contributor


Looking at your code, it looks like there's a path through identificationTool where cancelExecute could be called before queryDeferred has been set.

Have you got the rest of the code available?




Yes here is the "caller" of identificationTool.

function toolOnClick(map,qryUE,queryTaskUE)
{
 // IDENTIFICATION
 $('#identify').click(function () {
  if(activeTool == "identify_spot")
  {
   $('#identify_spot').removeClass("active_tool");
   activeTool = "";
   identificationTool(false,qryUE,queryTaskUE);
  }
  else
  {
   if(activeTool != "")
   {
    $('#'+activeTool).removeClass("active_tool");    
   }
   $('#identify_spot').addClass("active_tool");
   console.log("Identification: start");
   identificationTool(true,qryUE,queryTaskUE);
   activeTool = "identify_spot";
  }
    });
}


The function toolOnClick() is called from $(document).ready(function()); in the init function of my code. So when a user click on the identification tool the process of identification is started.

I tried your snippet but it doesn't seem to work. It seems that the featureSet is not working and the err function is always called.

function identificationTool(action,qryUE,queryTaskUE)
{
 console.log("identification? "+action)
 if(action == true )
 {
  dojo.connect(map, "onClick", function(evt) 
  {
   console.log("Identification: click");   
         qryUE.geometry = evt.mapPoint;
         //queryDeferred = queryTaskUE.execute(qryUE);
         var def = queryTaskUE.execute(qryUE,
       function (featureSet) 
       {
           alert("FeatureSet returned");
           showResults(featureSet);
       },
       function (err) 
       {
           alert("Error...but can't get at the message/reason that you expected to see, unfortunately.\n\ndef.canceled (sic) = " + def.canceled);
       }
   );
   def.cancel("A reason for cancelling can be provided here",/*not strict*/false);
         
         //queryDeferred.then(showResults,showError);
         
              });
       }
}


What am I missing to make this "work"?
0 Kudos
__Rich_
Deactivated User
You'll notice that in the snippet I provided that I am always calling def.cancel() hence why the error handler function is always being invoked - it's expected behaviour.

May I suggest that you wrap most (nearly all!) of the identify logic into a widget/module and let it handle executing/cancelling tasks, then all your UI component needs to do is delegate to the widget/module - it will be easier to maintain state within a sensible scope with this approach.
0 Kudos
YvanBérard
Regular Contributor
Yes I understand, but what I want to do is when I click on my identification button, the identification process is starting. But when the user click on the identification button again (to deactivate it --> when the var action == false ) I want the queryTask to be stopped/cancelled. That is where the dojo.deferrer.cancel is suppose to be working.

But it's not.

And I can't figure out how to make it stop. In other module (like navigation toolbar) there is a method that stop the action (navToolbar.deactivate()) and this is exactly what I want to do, but with the queryTask.


/************************************************************************************
 * �? COMPLETER
 */
function identificationTool(action,qryUE,queryTaskUE)
{
 var def;
 console.log("identification? "+action)
 if(action == true )
 {
  dojo.connect(map, "onClick", function(evt) 
  {
   console.log("Identification: click");   
                 qryUE.geometry = evt.mapPoint;
                 //queryDeferred = queryTaskUE.execute(qryUE);
                 def = queryTaskUE.execute(qryUE,
       function (featureSet) 
       {
           alert("FeatureSet returned");
           showResults(featureSet);
           
       },
       function (err) 
       {
           alert("Error...but can't get at the message/reason that you expected to see, unfortunately.\n\ndef.canceled (sic) = " + def.canceled);
       }
   );
        });
 }
 else
 {
  // HERE WE STOP THE EXECUTION
  //cancelExecute();
  // this is not working because "def" is undefined even if I created it at the begining of the function.
  //def.cancel("A reason for cancelling can be provided here",/*not strict*/false);
 }
}

/************************************************************************************
 * �? COMPLETER
 */
function cancelExecute() 
{
 console.log("identification queryDeferred("+queryDeferred+") to stop = "+queryDeferred.fired)
 if(queryDeferred && (queryDeferred.fired > 0)) 
 {
  console.log("Identification: stop");
  queryDeferred.cancel();
 }
}
0 Kudos
YvanBérard
Regular Contributor
May I suggest that you wrap most (nearly all!) of the identify logic into a widget/module and let it handle executing/cancelling tasks, then all your UI component needs to do is delegate to the widget/module - it will be easier to maintain state within a sensible scope with this approach.


Yes I'll try this approach and I'll come back if it works or not. Thanks.
0 Kudos
__Rich_
Deactivated User
Yes I understand, but what I want to do is when I click on my identification button, the identification process is starting. But when the user click on the identification button again (to deactivate it --> when the var action == false ) I want the queryTask to be stopped/cancelled. That is where the dojo.deferrer.cancel is suppose to be working.

But it's not.

And I can't figure out how to make it stop. In other module (like navigation toolbar) there is a method that stop the action (navToolbar.deactivate()) and this is exactly what I want to do, but with the queryTask.


/************************************************************************************
 * �? COMPLETER
 */
function identificationTool(action,qryUE,queryTaskUE)
{
 var def;
 console.log("identification? "+action)
 if(action == true )
 {
  dojo.connect(map, "onClick", function(evt) 
  {
   console.log("Identification: click");   
                 qryUE.geometry = evt.mapPoint;
                 //queryDeferred = queryTaskUE.execute(qryUE);
                 def = queryTaskUE.execute(qryUE,
       function (featureSet) 
       {
           alert("FeatureSet returned");
           showResults(featureSet);
           
       },
       function (err) 
       {
           alert("Error...but can't get at the message/reason that you expected to see, unfortunately.\n\ndef.canceled (sic) = " + def.canceled);
       }
   );
        });
 }
 else
 {
  // HERE WE STOP THE EXECUTION
  //cancelExecute();
  // this is not working because "def" is undefined even if I created it at the begining of the function.
  //def.cancel("A reason for cancelling can be provided here",/*not strict*/false);
 }
}

/************************************************************************************
 * �? COMPLETER
 */
function cancelExecute() 
{
 console.log("identification queryDeferred("+queryDeferred+") to stop = "+queryDeferred.fired)
 if(queryDeferred && (queryDeferred.fired > 0)) 
 {
  console.log("Identification: stop");
  queryDeferred.cancel();
 }
}

Of course def will be undefined as the function is effectively reentrant, the previous invocation (and any variables in it) is out of scope.

You invoke the function on the first click, on the second click you invoke the function again, completely separately ('fresh' if you like) from the first invocation, this is expected.

Make sense?
0 Kudos
YvanBérard
Regular Contributor
Of course def will be undefined as the function is effectively reentrant, the previous invocation (and any variables in it) is out of scope.

You invoke the function on the first click, on the second click you invoke the function again, completely separately ('fresh' if you like) from the first invocation, this is expected.

Make sense?


Yes you are right.

Thank's to you and to Mr. Eric Gosselin from ESRI Canada Tech Support, you helped me alot.

Mr. Gosselin suggest me to use the method dojo.disconnect()  (http://help.arcgis.com/en/webapi/javascript/arcgis/help/jshelp/inside_events.htm) and I had to modify my code so when I want to identify a new parcel, I need to click again on the identification button.

Here is my code to do so and this is working.

function toolOnClick(map,qryUE,queryTaskUE)
{
 // IDENTIFICATION
 $('#identify').click(function () 
 {
  var dojoClick=dojo.connect(map, "onClick", function(evt)  
  {
   identificationTool(qryUE,queryTaskUE,dojoClick,evt);
  });
    });
}

/************************************************************************************
 * �? COMPLETER
 */
function identificationTool(qryUE,queryTaskUE,dojoClick,evt)
{
  console.log("Identification: start");
     
     qryUE.geometry = evt.mapPoint;
     def = queryTaskUE.execute(qryUE,
   function (featureSet) 
   {
       showResults(featureSet);
       
   },
   function (err) 
   {
       alert("Error...but can't get at the message/reason that you expected to see, unfortunately.\n\ndef.canceled (sic) = " + def.canceled);
   }
  );

  console.log("Identification: stop");
  // kill the handler
  dojo.disconnect(dojoClick);
}


Again, thank's to you all!
0 Kudos