2013-03-31 115 views
8

這是我的Gruntfileoutput如何讓Grunt在運行另一個任務之前等待任務完成?

正如你可以在輸出中看到,有一對夫婦的相關異步任務的問題:

  1. imagemin被調用,下一個來直行。這使得它的輸出出現在任務的最後,這很麻煩;
  2. build,這是一個自定義任務,使用var done = this.async()並在完成命令後調用done();但是,如果我單獨運行任務,這隻能正常工作;用其他任務運行它也會使其運行異步;
  3. 隨着build運行後,jasmine沒有什麼可測試,因此是無用的。

有沒有辦法解決這個問題?

+0

我從來沒有與步兵的this.async問題()。可能是另一項任務的不良副作用?你有沒有嘗試你的任務鏈沒有imagemin? –

回答

7

我相信你的問題是這個任務:

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(); 
        }); 
      } 
    }); 

如果你有多個文件夾,無論是異步()和()完成將被多次調用。異步是作爲一個簡單的標誌(true/false)實現的,並且被調用一次。第一次完成()調用允許任何後續任務運行。

有很多方法可以將調用移動到異步並完成循環。快速谷歌搜索如:nodejs how to callback when a series of async tasks are complete會給你一些額外的選擇。一對夫婦的快速(&髒)的例子:

// 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'); 
    } 
})(); 

- 或 -

// 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

我以前說過,但不知道如何解決。如果我將異步移出,文件夾創建將與其他任務一起發生。 – igorsantos07

+0

我已經更新了一些關於如何在所有工作完成時回調的示例。 – dc5

+0

看起來很酷!儘管我已經離開了這個項目很長一段時間了,但我認爲它可以正常工作。看起來開發者也解決了一些導致這個問題的問題,但答案很好。這麼晚纔回復很抱歉! – igorsantos07

0

正如你可以在閱讀Grunt documentation

如果一個任務是異步的,這必須調用.async方法來指示 Grunt等待。它返回一個「完成」功能的句柄,該功能在任務完成時應調用 。

和短的例子是類似於:

// 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 
});