2013-07-10 15 views
12

Ho bisogno di eseguire 3 funzioni in un ritardo di 1 secondo.Alternativo setTimeout annidato?

per semplicità queste funzioni sono:

console.log('1'); 
console.log('2'); 
console.log('3'); 

avrei potuto fare questo: (molto brutta)

console.log('1') 
setTimeout(function() { 
    setTimeout(function() { 
     console.log('2') 
     setTimeout(function() { 
      console.log('3') 

     }, 1000) 
    }, 1000) 

}, 1000) 

Oppure potrei creare un array di funzioni e utilizzare setInterval con global contatore.

C'è qualche elegante modo di fare questo?

(la funzione numero n.2 non dipende dalla funzione numero 1 ... quindi - ogni secondo esegue la funzione successiva.).

+0

Se non sono dipendenti e tali, perché hanno bisogno di eseguire in tempi diversi? (Assicurati che sia necessario) Potresti usare semplicemente 3 timeout separatamente, uno a 1 secondo, il secondo a 2 secondi e così via ... – Salketer

+1

usa setTimeout con loop ... per (...) {setTimeout (function() {}, Indice 1000 *); } o qualcosa di simile alla pressione della rete di @Salketer – Givi

+0

? perché è importante? –

risposta

13

Si può usare qualcosa di simile con setTimeout:

var funcs = [func1, func2, func3], 
    i = 0; 

function callFuncs() { 
    funcs[i++](); 
    if (i < funcs.length) setTimeout(callFuncs, 1000); 
} 
setTimeout(callFuncs, 1000); //delay start 1 sec. 

o avviare semplicemente chiamando callFuncs() direttamente.

Aggiornamento

Un approccio setInterval (essere consapevoli del rischio di chiamata stacking):

var funcs = [func1, func2, func3], 
    i = 0, 
    timer = setInterval(callFuncs, 1000); 

function callFuncs() { 
    funcs[i++](); 
    if (i === funcs.length) clearInterval(timer); 
} 
+1

@RoyiNamir Perché dovresti moltiplicare l'indice per 1000? ... – Snuffleupagus

+0

mio male. eliminazione. –

+0

questo è quello che ho pensato (già menzionato nella mia domanda) - ma volevo sapere se ci sono più soluzioni ... –

2
setTimeout(function(){console.log('1')}, 1000); 
setTimeout(function(){console.log('2')}, 2000); 
setTimeout(function(){console.log('3')}, 3000); 
9

Supponendo che si esegue su un browser moderno o ha aggiunto il supporto per array. mappa questo è abbastanza conciso:

[func1, func2, func3].map(function (fun, index) { 
    setTimeout(fun, 1000 + index * 1000); 
} 
1

Penso che il modo più semplice per farlo è quello di creare alcune chiusure all'interno di una funzione.
Per prima cosa ricorderò che si ha grande interesse nell'uso di setInterval, poiché il sovraccarico di setTimeout potrebbe far scattare 10 ms fuori target. Quindi, specialmente se si utilizza l'intervallo breve (<50ms), si preferisca setInterval. Quindi dobbiamo memorizzare l'array di funzioni, l'indice della funzione più recente eseguita e un riferimento all'intervallo per interrompere le chiamate.

function chainLaunch(funcArray, time_ms) { 
    if (!funcArray || !funcArray.length) return; 
    var fi = 0; // function index 
    var callFunction = function() { 
     funcArray[fi++](); 
     if (fi==funcArray.length) 
       clearInterval(chainInterval); 
    } ; 
    var chainInterval = setInterval(callFunction, time_ms); 
} 

Rq: Si potrebbe voler copiare la funzione di matrice (funcArray = funcArray.slice(0);)
RQ2: Si potrebbe desiderare di ciclo all'interno dell'array
RQ3: si potrebbe desiderare di accettare argomenti addizionale per chainlaunch. recuperarli con var funcArgs = arguments.slice(3); e utilizzare applicare sulle funzioni: funcArray[fi++].apply(this,funcArgs);

In ogni caso il seguente test funziona:

var f1 = function() { console.log('1'); }; 
var f2 = function() { console.log('2'); }; 
var f3 = function() { console.log('3'); }; 

var fArr = [f1, f2, f3]; 

chainLaunch(fArr, 1000); 

come si può vedere in questo violino: http://jsfiddle.net/F9UJv/1/ (aprire la console)

0

Ci sono qui due metodi. Uno con setTimeout e un altro con setInterval. Il primo è migliore secondo me.

for(var i = 1; i++; i<=3) { 
 
    setTimeout(function() { 
 
     console.log(i); 
 
    }, 1000*i); 
 
} 
 
// second choice: 
 
var i = 0; 
 
var nt = setInterval(function() { 
 
     if(i == 0) return i++; 
 
     console.log(i++); 
 
     if(i>=3) clearInterval(nt); 
 
    }, 1000);

1

C'è un nuovo tipo di funzione di dichiarazione chiamati generatori a ES6 (a.k.a ECMAScript 6, es2015). È incredibilmente utile per questa situazione e rende il tuo codice asincrono un aspetto sincrono. es6 è l'ultimo standard di JavaScript dal 2015. Funziona con i browser moderni ma è possibile utilizzare Babel e il suo polyfill javascript per utilizzare i generatori ora anche sui browser più vecchi.

Here è un tutorial su generatori.

I myDelayedMessages funzione sotto è un esempio di un generatore. Esegui è una funzione di supporto che prende una funzione di generatore che chiama e fornisce una funzione per far avanzare il generatore come primo argomento della funzione del generatore che ha chiamato.

function delay(time, callback) { 
 
     setTimeout(function() { 
 
     callback(); 
 
     }, time); 
 
} 
 

 
function run(generatorFunction) { 
 
    var generatorItr = generatorFunction(resume); 
 
    function resume(callbackValue) { 
 
    generatorItr.next(callbackValue); 
 
    } 
 
    generatorItr.next() 
 
} 
 

 
run(function* myDelayedMessages(resume) { 
 
    for(var i = 1; i <= 3; ++i) { 
 
    yield delay(1000, resume); 
 
    console.log(i); 
 
    } 
 
});

Questa è una panoramica del codice che è simile alla visione finale sopra del tutorial.

  1. run prende il nostro generatore e crea una funzione di ripresa. run crea un oggetto generatore-iteratore (la cosa che viene chiamata in seguito), fornendo il ripristino di .
  2. Poi si avanza il generatore-iteratore un passo per dare il tutto fuori.
  3. Il nostro generatore incontra il primo rendiconto e chiama il ritardo.
  4. Quindi il generatore si interrompe.
  5. il ritardo termina dopo 1000 ms e le chiamate riprendono.
  6. resume dice al nostro generatore di avanzare di un singolo passaggio.
  7. nostro generatore continua dal punto esso prodotto in poi console.logs i, che è 1, allora il ciclo continua
  8. nostro generatore incontra la seconda chiamata a cedere, chiamate ritardare e pause di nuovo.
  9. ritardo attende 1000ms e infine chiama la callback riprendere. resume fa avanzare nuovamente il generatore.
  10. Il nostro generatore continua dal punto in cui è stato restituito a console.logs i, che è 2, quindi continua il ciclo.
  11. ritardo attende 1000ms e infine chiama la callback riprendere. resume fa avanzare nuovamente il generatore.
  12. Il nostro generatore continua dal punto in cui è stato restituito a console.logs i, che è 3, quindi continua e termina il ciclo.
  13. Non ci sono più chiamate da cedere, il generatore termina l'esecuzione.