Stop executing a Javascript function to perform another function

Asked

Viewed 7,147 times

1

I am developing a system using angular and have the following function:

    function drawLatLong(i, arrayIdColetor) { 
.....
         (não exibi o código por ser grande e achar desnecessário que vcs o analisem)
.....
      });

This function is invoked in a for:

for(var j = 0; j < $kinvey.arrayIdColetor.length;  j++){
   drawLatLong(j, $kinvey.arrayIdColetor);          
 }

The function drawLatLong that is invoked N times according to FOR, it takes a considerable time to be executed as it does relatively heavy searches in the database.

The problem I’m having is that if the user invokes another function without that function drawLatLong has finished, the system does not behave as it should.

Would there be any way to keep this situation under control? That is, only allow the user to perform another function after the drawLatLong has been finalized? Or it would be possible to interrupt the execution of the function drawLatLong in between, if another function is invoked by the user?

I hope I made myself clear. Thanks in advance.

  • You were of course yes. I never thought of calling a call function for the bank in a loop. We can start the solution by taking this call from inside the loop. Imagine if you get stuck in this loop and it gets infinite.... crash in your database.

  • a simple "if" condition would not solve your problem?

  • @durtto I need to make this call inside the loop because I search for latitude and longitude according to the idColetor (1 idColetor identifies 1 vehicle), so if I have 3 idColetors (or 3 vehicles) I need to pick up the coordinates of each of the vehicles and print on the screen, I’m not sure I made myself clear. Abs.

  • @Ivanferrer using an if how could I interrupt the execution of one function in the middle to execute another that was invoked by the user? Obg

  • The idea is not to interrupt the script, but to get out of it...

  • To interrupt you can use try { ...} catch(err) { ... } finally { ... }.

  • Another thing you can do is give one break; in your noose for, if a condition or other function is invoked.

  • @S_A, thought to run the drawLatLong on a Webworker? by doing this, you will not occupy your main thread.

  • @Tobymosque follows what I want to do: when opening the screen I search in the bank the latitude and longitude of several vehicles (for this I use the for(var j = 0; j < $kinvey.arrayIdColetor.length; j++){ ... }. The function drawLatLong is responsible for displaying these coordinates on the screen, and each vehicle will have its outline. The problem is that while this is done, it may be that the user selects to see the tracing of only 1 vehicle, thus the function of displaying only one tracing runs in parallel with the function drawLatLong that is still running. I think Webworker n would help. What do you think? Obg

  • look, this will depend on the implementation, when loading the page you can use a WebWorker by vehicle and load the longitude and the latitude in parallel and only release the page when all WebWorker send the return message... this way the method to display only one stroke will not need to redo the query, just apply a filter on the page... but as said, everything depends on its implementation.

  • It will probably work @Tobymosque, but first I will try some alternative that requires me less changes to the code. Obg

Show 6 more comments

3 answers

1

To do this you will need to use .promise(). With it you can do asynchronous programming with javascript.

Take this example

$( "button" ).on( "click", function() {
  $( "p" ).append( "Started..." );

  $( "div" ).each(function( i ) {
    $( this ).fadeIn().fadeOut( 1000 * ( i + 1 ) );
  });

  $( "div" ).promise().done(function() {
    $( "p" ).append( " Finished! " );
  });
});

1


You can use a callback for that next "for" only be executed at the end of drawLatLong.

function drawLatLong(i, arrayIdColetor, callback) { 
    .....
    (não exibi o código por ser grande e achar desnecessário que vcs o analisem)
    .....
    callback(); 
};

In place of for you can use a function in which you will be "called" (executed) once the drawLatlong has finished.

function callFor(j, arrayIdColetor) {
  if (j < arrayIdColetor.length)
    drawLatLong(j, arrayIdColetor, function() {
      callFor(j + 1, arrayIdColetor)
    });
}
callFor(0, $kinvey.arrayIdColetor);

The following is a demonstration (with amendment proposed in the comment):

    var $kinvey = {
      arrayIdColetor: [5, 12, 124, 636, 47, 45]
    }

    function addEl(txt) {
      var li = document.createElement('li');
      li.innerHTML = txt;
      document.getElementById('demo').appendChild(li);
    }

    function add400(callback) {
      addEl(400);
      callback();
    }

    function drawLatLong(i, arrayIdColetor, callback) {
      addEl(arrayIdColetor[i]);
      setTimeout(function() { //faz uma execução assíncrona
        add400(function() {
          setTimeout(function() { //faz outra execução assíncrona
            //esse callback() foi passado como parâmetro da função "drawLatLong"
            callback();
          }, 1000);
        });
      }, 1000);
    };

    function callFor(j, arrayIdColetor) {
      if (j < arrayIdColetor.length)
        drawLatLong(j, arrayIdColetor, function() {
          callFor(j + 1, arrayIdColetor)
        });
    }
    callFor(0, $kinvey.arrayIdColetor);
<ul id="demo"></ul>

  • Suppose while printing on the screen the numbers 5, 12, 124... the user invokes a function that prints the number 400, for example. How could I interrupt the print of the numbers 5,12,124,636,47 and 45 to print only the number 400? If that is possible I will be able to solve my problem. Thank you very much.

  • If you got an answer, mark as accepted. Thank you

  • as soon as I get Mark @durtto

  • this function that printed 400 needs to follow the same methodology of an asynchronous function, so callback would "call" (execute) the callback of the previous one that was passed as a function. I’ll change the question to give you an example.

  • @Leandroamorim and if I want the add400 function to be executed only after all callFor is executed? Thank you

  • @Leandroamorim a pg is not available.

  • 1

    @S_A https://jsfiddle.net/LAmorim/L3v5xcw1/

Show 2 more comments

0

A simple IF condition would not solve the problem?

var executandoAcao = function () {
 for (var j = 0; j < $kinvey.arrayIdColetor.length;  j++) {
   drawLatLong(j, $kinvey.arrayIdColetor);          
 }
return true;
}();

if (executandoAcao) {
      outrafuncao();
}

If you want to interrupt in the middle of the loop, doing so also works:

 function executandoAcao(interromper) {

     for (var j = 0; j < $kinvey.arrayIdColetor.length;  j++) {
             drawLatLong(j, $kinvey.arrayIdColetor);
          if (interromper) {
             break;
          }          
     }
    return true;
 }

 var interromper = (outraFuncao) ? true : false;
 executandoAcao(interromper);

 var outraFuncao = function() {
     var promise = false;
     //aqui a outra função que vc quer executar
     $('#elemento').on('click', function() {
         promise = true;
     });
 return promise;
 }();
  • actually works, but I continue with the following problem: suppose this is will invoke the function drawLatLong 3x, when interrupting execution I may have already executed the drawLatLong 2x, right? That is, in addition to interrupting as you suggested, tbm will have to make the function invoked by the user run only after leaving the for. I don’t know if I was clear. Obg

Browser other questions tagged

You are not signed in. Login or sign up in order to post.