2013-03-31 11 views
8

Ecco il mio Gruntfile e lo output.Come fare in modo che Grunt attenda il completamento di un'operazione prima di eseguirne un altro?

Come potete vedere nell'output, ci sono un paio di questioni relative ai compiti asincroni:

  1. imagemin è chiamata ed il successivo arriva dritto. Questo fa apparire il suo output alla fine delle attività, ciò che è abbastanza disordinato;
  2. build, che è un'attività personalizzata, è utilizzando var done = this.async() e chiamando done() dopo aver terminato il comando; tuttavia, questo funziona correttamente solo se eseguo il task da solo; eseguirlo con un altro compito lo rende anche asincrono;
  3. Con build in esecuzione più tardi, jasmine non ha nulla da testare e quindi è inutile.

C'è un modo per risolvere questo comportamento?

+0

non ho mai avuto problemi con this.async di Grunt(). Probabilmente un cattivo effetto collaterale di un'altra attività? Hai provato la tua catena di attività senza imagemin? –

risposta

7

Credo che il vostro problema è con questo compito:

grunt.registerTask('prepare-dist', 'Creates folders needed for distribution', function() { 
      var folders = ['dist/css/images', 'dist/imgs/icons']; 
      for (var i in folders) { 
        var done = this.async(); 
        grunt.util.spawn({ cmd: 'mkdir', args: ['-p', folders[i]] }, function(e, result) { 
          grunt.log.writeln('Folder created'); 
          done(); 
        }); 
      } 
    }); 

Se si dispone di più cartelle, sia asincrona() e fatto() sarà chiamato più volte. Async è implementato come un semplice flag (vero/falso) e deve essere chiamato una sola volta. La prima chiamata done() consente l'esecuzione di qualsiasi attività successiva.

Ci sono molti modi per spostare le chiamate in asincrono e terminare il ciclo. Una rapida ricerca su google su qualcosa di simile: nodejs how to callback when a series of async tasks are complete ti darà alcune opzioni aggiuntive. Un paio di rapidi (& sporche) esempi:

// Using a stack 
(function() { 
    var work = ['1','2','3','4','5'] 


    function loop(job) { 
     // Do some work here 
     setTimeout(function() { 
      console.log("work done"); 

      work.length ? loop(work.shift()) : done(); 
     }, 500); 
    } 

    loop(work.shift()); 

    function done() { 
     console.log('all done'); 
    } 
})(); 

- o -

// Using a counter (in an object reference) 
(function() { 
    var counter = { num: 5 } 

    function loop() { 
     // Do some work here 
     setTimeout(function() { 
      --counter.num; 

      console.log("work done"); 

      counter.num ? loop() : done(); 
     }, 500); 
    } 

    loop(); 

    function done() { 
     console.log('all done'); 
    } 
})(); 
+0

L'ho già detto prima, ma non ho idea di come sistemare. Se esco asincrono, la creazione della cartella avverrà insieme ad altre attività. – igorsantos07

+0

Ho aggiornato la mia risposta con un paio di esempi su come richiamare quando TUTTO il lavoro è completo. – dc5

+0

Sembra fantastico! Anche se sono fuori dal progetto da un po 'di tempo, penso che funzionerebbe bene. Sembra che lo sviluppatore abbia anche risolto un problema che causava questo problema, ma la risposta è comunque buona. Scusa per il ritardo della risposta! – igorsantos07

0

Come si può leggere nel Grunt documentation:

Se un'attività è asincrona, questo Il metodo .async deve essere invocato per indicare a Grunt di attendere. Restituisce un handle a una funzione "completata" che dovrebbe essere chiamata quando l'attività è stata completata.

E un breve esempio potrebbe essere simile a:

// Tell Grunt this task is asynchronous. 
var done = this.async(); 

// Your async code. 
fetchData(url).then(data => { 
    console.log(data); 
    done(); 
}).catch(error => { 
    console.err(error); 
    done(false); // false instructs Grunt that the task has failed 
}); 
Problemi correlati