Grunt で非同期タスクを調べてみたが・・・。

  • 3
    いいね
  • 0
    コメント
この記事は最終更新日から1年以上が経過しています。

結論

まぁ、結論から言うとそらしょうがないけどなんだかなって感じです。 grunt-typescript 作ってるときは意識してなかったから多分ミラクルが起こってたのかと思われます。

で、Grunt のタスクで非同期タスク作ろうとしてあれっ?てなったから調べたって話です。

とりあえず、公式ドキュメントどおりにやってみる

http://gruntjs.com/creating-tasks

上を読むとどうやら、this.async 使えって書いてある。なので、下のように書いてみる。

module.exports = function(grunt){
  grunt.registerTask("default", "非同期の確認", function(){
    var done = this.async();
  });
};

で、動かすとすぐ終わる。以下がコンソールの写し。予想では done 呼んでないからずーっと待機されると想像してました。想定外の結果。

user@machine /d/Work/TempSrc/gruntAsyncTest
$ grunt
Running "default" task

user@machine /d/Work/TempSrc/gruntAsyncTest

setTimeoutを仕掛けてみる

ドキュメントでは大抵 setTimeout を仕掛けてるので同じように仕掛けてみる。

module.exports = function(grunt){
  grunt.registerTask("default", "非同期の確認", function(){
    var done = this.async();
    setTimeout(function(){
      console.log("終わるよ!");
    }, 1000);
    console.log("仕掛けたよ!");
  });
};

動かしてみる。

user@machine /d/Work/TempSrc/gruntAsyncTest
$ grunt
Running "default" task
仕掛けたよ!
終わるよ!

user@machine /d/Work/TempSrc/gruntAsyncTest

おっ、setTimeout の完了を待った模様。予想では、待たずにそのまま最初と同じように終わると思ってた。ちなみに、this.async しないで、単純に流すと以下のようになる。

user@machine /d/Work/TempSrc/gruntAsyncTest
$ grunt
Running "default" task
仕掛けたよ!

Done, without errors.

user@machine /d/Work/TempSrc/gruntAsyncTest

"終わるよ!"ってメッセージが出て無い。で、よく見ると "Done, without errors." ってメッセージが出てる。今までは全く出て無かった。this.async() を戻して、 setTimeout の中で done 呼んでやると、ちゃんと "Done, without errors." ってメッセージが出るらしい。

Grunt 自体終わってる気がする

this.asyncして done せずに終わるとメッセージが出ないってことは Grunt は終わったと思ってない。と、思われる。でも、コンソール自体は終わる。ってことは、つまるところ node 側が処理が全部なくなったから終わりだね。って終わらしてるような気がする。ってことは Grunt は this.async 呼ばれても done を渡すだけで、待機とかはなにもしてないのでは。と思われる。

ってことで、中を見てみた。

https://github.com/gruntjs/grunt/blob/master/lib/util/task.js#L236
asyncが呼ばれたらフラグ立てて、complete を実行する関数を返してる。

https://github.com/gruntjs/grunt/blob/master/lib/util/task.js#L253
で、処理実行して終わった後に、フラグ確認して、フラグ立ってなかったら complete 実行するけど、フラグ立ってなかったら何もしない。

ってことで、やっぱりそのまま流れていって、 node 的には処理が全部なくなったから終わらせてる感じ。

んー、 grunt が内部的に setTimeout かなんかでくるくる回してフラグ確認してくれると使う側からはもっとわかりやすいんやけど、まぁ、パフォーマンスとかいろいろ考えると、何とも言えんとこやけど微妙な気がしないでもない。

クルクル回すとやっぱり終わらない

ってことで、書いてみた。やっぱり終わらないっす。

module.exports = function(grunt){
  grunt.registerTask("default", "非同期の確認", function(){
    var done = this.async(), 
        //クルクル回す処理
        wait = function(){
          setTimeout(function(){
            console.log("待ってます。");
            wait();
          }, 1000);
        };
      //クルクル開始
      wait();
      console.log("仕掛けたよ!");
  });
};

これコールスタック溜まりそう・・・。いや、 setTimeout の時点でいったん消えそうやから大丈夫か?