2015-05-28 13 views
7

Ho il codice qui sotto:Delay ogni iterazione del ciclo in js nodo, asincrono

var request = require('request'); 
var cheerio = require ("cheerio"); 
var async= require("async"); 

var MyLink="www.mylink.com"; 

    async.series([ 

     function(callback){ 
      request(Mylink, function (error, response, body) { 
       if (error) return callback(error); 
       var $ = cheerio.load(body); 
       //Some calculations where I get NewUrl variable... 
       TheUrl=NewUrl; 
       callback(); 
      }); 
     }, 
     function(callback){ 
      for (var i = 0; i <=TheUrl.length-1; i++) { 
       var url = 'www.myurl.com='+TheUrl[i]; 
       request(url, function(error, resp, body) { 
        if (error) return callback(error); 
        var $ = cheerio.load(body); 
        //Some calculations again... 
        callback(); 
       }); 
      }; 
     } 
     ], function(error){ 
     if (error) return next(error); 
    }); 

Qualcuno ha un suggerimento su come posso ritardare ogni iterazione del ciclo nel for loop? Ad esempio, il codice attende 10 secondi dopo il completamento di ogni iterazione. Ho provato setTimeout ma non sono riuscito a farlo funzionare.

risposta

11

È possibile impostare un timeout per l'esecuzione del codice a intervalli crescenti come questo:

var interval = 10 * 1000; // 10 seconds; 

for (var i = 0; i <=TheUrl.length-1; i++) { 
    setTimeout(function (i) { 
     var url = 'www.myurl.com='+TheUrl[i]; 
     request(url, function(error, resp, body) { 
      if (error) return callback(error); 
      var $ = cheerio.load(body); 
      //Some calculations again... 
      callback(); 
     }); 
    }, interval * i, i); 
} 

Quindi la prima si corre subito (intervallo * 0 è 0), secondo corre dopo dieci secondi, ecc.

È necessario inviare i come parametro finale nello setTimeout() in modo che il suo valore sia associato all'argomento della funzione. Altrimenti il ​​tentativo di accedere al valore dell'array sarà fuori limite e otterrai undefined.

+0

Perché non è possibile cambiare la prossima ultima riga da '}, intervallo * i, i);' a '}, intervallo di * 1, i);', 'da I a 1' ? Il codice non funziona quindi, se voglio un intervallo costante. – user1665355

+0

'setTimeout()' ritorna immediatamente. Non si siede lì e aspetta il timeout prima di restituire il controllo al ciclo 'for'. Quindi se usi 'interval * 1' (che è lo stesso di' interval', allora stai facendo funzionare tutti i dieci secondi in futuro tutti in una volta (più o meno - saranno a pochi millisecondi di distanza, ma è così Ma se usi 'intervallo * i', questo è" subito "la prima volta," dieci secondi nel futuro "la seconda volta nel ciclo," venti secondi nel futuro "la terza volta, ecc. – Trott

+0

Ok, ho provato "intervallo * 1" ma non ho ottenuto risultati ... Ma capisco cosa intendi! Grazie – user1665355

9

Poiché si sta già utilizzando async, async.wilst farebbe bene come sostituto per for.

whilst è una funzione asimmetrica while -like. Ogni iterazione viene eseguita solo dopo che l'iterazione precedente ha chiamato il suo callback di completamento. In questo caso, possiamo semplicemente posticipare l'esecuzione della callback di completamento di 10 secondi con setTimeout.

var i = 0; 
async.whilst(
    // test to perform next iteration 
    function() { return i <= TheUrl.length-1; }, 

    // iterated function 
    // call `innerCallback` when the iteration is done 
    function(innerCallback) { 
     var url = 'www.myurl.com='+TheUrl[i]; 
     request(url, function(error, resp, body) { 
      if (error) return innerCallback(error); 
      var $ = cheerio.load(body); 
      //Some calculations again... 

      // wait 10 secs to run the next iteration 
      setTimeout(function() { i++; innerCallback(); }, 10000); 
     }); 
    }, 

    // when all iterations are done, call `callback` 
    callback 
); 
+0

È possibile impostare un ritardo in un momento specifico? Nell'esempio ogni 30 minuti? – user1665355

10

Un'altra alternativa sarebbe utilizzare async.eachSeries. Per esempio:

async.eachSeries(TheUrl, function (eachUrl, done) { 
    setTimeout(function() { 
     var url = 'www.myurl.com='+eachUrl; 
     request(url, function(error, resp, body) { 
      if (error) return callback(error); 
      var $ = cheerio.load(body); 
      //Some calculations again... 
      done(); 
     }); 
    }, 10000); 
}, function (err) { 
    if (!err) callback(); 
}); 
Problemi correlati