javascript loop with Sleep

Asked

Viewed 8,595 times

4

How would I make a for or any kind of loop showed the result respecting the time of 1 second for example between an iteration and another?

I tried it and it didn’t work:

for( var i=0; i < 10; i++ ){
    setTimeout(function (){console.log('valor de i='+i); },1000);
}

The purpose of these intervals occurs in the following situation:

dup.crtPdf=function(flag){    
    var array = $('#dup-jqxGrid02').jqxGrid('getrows');                          
    dup.arrayCrt = array.slice(0);                                               
    var tempo =0;
    for(var i=0; i<array.length; i++){                                  
            var obj = new Object();                  
            switch (flag){
                case 1: obj.ireport = "/reports/samples/crt_frete_pago_completo"; break; // CASO FOR IGUAL A 1 - FRETE PAGO
                case 2: obj.ireport = "/reports/samples/crt_a_pagar_completo"; break;    // CASO FOR IGUAL A 1 - FRETE À PAGAR
            }            
            obj.parametros = new Array({"id" : dup.arrayCrt.pop().con_id });
            custom.ajax(obj,'registrar',"../relatorios/imprimir.php");
            window.open("../relatorios/imprimir.php");                                          
    }               
};

Print file.php

    <?php    
    /* @author Maison K. Sakamoto
     * Data: 20/09/2013
     * @version 0
     * Arquivo Generico para imprimir quaisquer iport 
     * 
     * COMO USAR:
     * 1º FAZER UMA CHAMADA PARA A FUNÇÃO REGISTRO
     *      DEVERA FAZER UM POST VIA AJAX COM UM OBJETO CONTENDO DOIS PARAMETROS
     *      PARAMETRO 1 - STRING CONTENDO O PATH/NOME DO ARQUIVO.JRXML
     *      PARAMETRO 2 - ARRAY DE PARAMETROS NECESSÁRIOS PARA O JRXML FAZER A CONSULTA NO BANCO DE DADOS
     * 2º NO RETORNO DO AJAX(success) DEVERÁ SER FEITO UM "window.open()" CHAMANDO ESTE ARQUIVO
     */
    include_once 'server/Adl/Configuration.php';
    include_once 'server/Adl/Config/JasperServer.php';
    include_once 'server/Adl/Config/Parser.php';
    include_once 'server/Adl/Integration/RequestJasper.php';
    @session_start();                                                           //ABRE AS VARIAVEIS DE SESSÃO
    @$funcao = $_REQUEST['funcao'];                                             //PEGANDO O NOME DA FUNÇAO 
    is_string($funcao) ? call_user_func($funcao) : imprimir();                  //VERIFICA SE É UM REGISTRO OU IMPRESSÃO    
    function imprimir(){                                                        //FUNÇÃO IMPRIMIR        
        $obj = (object) unserialize($_SESSION['obj']);                          //PEGANDO DA SESSION E PARSE EM OBJECT                
        $jasper = new Adl\Integration\RequestJasper();                          //INSTANCIA DA API JASPERSERVER        
        header('Content-type: application/pdf');                                //CABEÇALHO SETANDO TIPO PDF
        echo $jasper->run($obj->ireport,'PDF',$obj->parametros[0]);             //EXECUÇÃO        
    }                                                                           //FIM DA FUNÇÃO IMPRIMIR
    function registrar(){                                                       //FUNCÃO REGISTRA OS PARAMETROS EM SESSÃO
        $_SESSION['obj'] = serialize($_REQUEST['obj']);                         //OBJETO COM ATRIBUTO "IREPORT" E "PARAMETROS"        
        echo json_encode(Array("info"=>"ok"));                                  //RETORNO DE CONFIRMAÇãO DO AJAX        
    }                                                                           //FIM DA FUNÇÃO REGISTRAR        
?>

Namely the custom.ajax(obj,'registrar',"../relatorios/imprimir.php"); makes the record on $_SESSION then I open the print.php file with the window.open("../relatorios/imprimir.php"); so this file becomes generic and can be used several times changing only the parameters in ajax, indicating which iReport will be called

  • @Danielomine n o m e u c a s I simplified the question just to spare understanding of the purpose, that in my case would shoot ajax to php pages that makes use of $_SESSION that this had not time to record in Ssion, so I focused on the problem that was to fire javascript at intervals, the purpose I’m sure is not duplicated.

6 answers

7


Hello you can use this way,

 var i = 0;
 var loop = setInterval(function(){ 
   console.log("valor de i="+i); 
   if(i == 10){
      clearInterval(loop);
   }
   i++;
 }, 1000);
  • Thank you, that’s what I needed

5

you can combine a closure with a setInterval, so that it works in a similar way to a while

(function () {
  var indice = 0;
  var limite = 10;
  
  var interval = setInterval(function (){
    console.log('valor de indice=' + indice); 
    
    indice++;
    if (indice == limite) {
      clearInterval(interval);
    }
  },1000);
})();

Follows an alternative inspired by Parallel.For of C#, in this case I have a Function to manage the for.

var _for = function (fromInclusive, toExclusive, callback){
  var indice = fromInclusive
  var interval = setInterval(function () {
    callback(indice);
    indice++;
    if (indice == toExclusive) {
      clearInterval(interval);
    }
  }, 1000);
}

_for(0, 10, function (i) {
  console.log("valor de i = " + i);
});

  • Very interesting your second solution, shows you know the technical background in javascript parabens!

  • @Sneepsninja, I believe the biggest problem in this case is not the loop itself, but control the scope of the variable i, I just didn’t understand why #Guilhermelopes' response won more up votes if he answered seconds later ;D

  • I voted in yours because I also saw your answer seconds before, but I gave the acceptance to stimulate the new here in SOPT, it is reassured that the up vote or the accepted does not mean that your answer is inferior in anything saw!

  • @Sneepsninja, as for acceptance, I’d do the same.

2

for( var i=0; i < 10; i++ ){
    setTimeout(function (){console.log('valor de i='+i); },i*1000);
}
  • Opa this is already a step forward, but the value of i was worth 10 in all iterations ?

1

You already have good answers on how to do this with the setInterval then I won’t go that way.

You can create a function to wait for the desired period and call it after each loop, this way:

for( var i=0; i < 10; i++ ){
   console.log('valor de i='+i); 
	 aguarde(1000);
}

function aguarde(ms){
   var inicio = new Date().getTime();
   var fim = inicio;
   while(fim < inicio + ms) {
     fim = new Date().getTime();
  }
}

Source: Javascript - Wait 5 Seconds before executing next line

  • It’s a terrible idea to block the thread to make a delay of 1s. remember that Avascript normally runs only on a thread and requires a non-blocking development model.

  • @Tobymosque I agree that this option should not "be used", so to speak. I just wanted to show a "different" form from the ones presented. I guess I didn’t put it well in the answer.

1

Alternative with Settimeout() :

var setTimeOut = (function(){
    var callback = null;
    var time = null;
    var iterate = null;

    if(!!iterate) iterate = 1;
    if(!!time) time = 1;

    var k = 1;
    var loop = function(){
        setTimeout(function(){
            if(typeof(callback) == 'function')
                callback(k);
            if(k < iterate){
                loop();
                k++;
            }
        }, time)
    };

    return function(c, t, i){
        callback = c;
        time = t;
        iterate = i;
        loop();
    }
})();
setTimeOut(function (i){console.log('valor de i='+i); },1000, 5)

1

I’ll explain how to do with setTimeout by explaining why Rodrigo’s method made the i be worth 10 every time.

setTimeout It’s an asynchronous call. This means that by the time the first setTimeout triggered the received function, the loop had already made its 10 iterations long ago. The variable i received as a parameter by the function is only a reference, and this reference already has the value 10, since this is its value in the last loop iteration. The variable i remains alive as long as a function has a reference to it, in which case several functions still have.

How to solve this?

for(var i = 0; i < 10; i++){

    (function(indice) {
        setTimeout(function() {
            console.log("Valor de i=" + indice)
        }, indice*1000)
    })(i); // uma chamada de função ocorre aqui, fixando o valor de indice para a função interna

}

This works because, at each iteration, a function is actually called and not just defined. The parameter value is evaluated at the time of passageway and not at the time of defining the function.

Browser other questions tagged

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