Node jsで始めるfilesystem5 非同期処理

javascript

jsでぶつかる壁の一つ非同期処理。Adobe Extensionだと基本jsxとの通信くらいしか使用しないですがNode moduleを色々使用したり外部との通信をやったりしていくうちにExtension開発者も徐々にぶつかる壁です。同期処理は上から下にコードを書いていけば上から下に処理を実行しますが非同期処理は処理が実行されてから終了するまで他の処理と同期しないので上から下に順番に処理を実行してくれません。誰もが最初に驚く壁だと思います。そして面倒くさいと感じるでしょう。しかし今日この非同期処理はjsと切っても切れない関係になっていてwebsiteを作る時もクライアントサイドでもがんがん使われているくらいです。Adobe jsxだけで完結したくない場合は習得必須とも言えます。

という事でsetTimeout関数を使った非同期の簡単なコードで色々サンプルを書いていきます。最初は単純な非同期関数内で呼び出されるconsoleと外で呼び出されるconsoleです。非同期関数の外でfinishedと最後に呼び出されるようにするつもりでコードを書きますがどうでしょう?

finishedとtimeOut関数を実行後に出てほしいのに実際は先にfinishedと表示されます。非同期関数内の値をreturnで返して関数の外で受け取ってればいんじゃね?と思った事もありましたが残念ながら非同期関数内でreturnで値を返してもundefinedしか返ってきません。

どうすれば良いでしょうか?解決策として非同期関数内に続けて書いていくかcallbackで次に実行する関数を渡す方法があります。

しかしこれ、非同期処理が常に単体での実行だったら良いですが例えば非同期処理が二つ、三つ、四つと重なるとどうなるでしょうか?

一気によくわからない感じになりました。ネストをもっと浅くして見易くするにはどうするか、という先人達の苦労の末に生まれたのがPromiseです。

Promiseという見慣れないオブジェクトが出てきました。返されたpromiseオブジェクトは実行後(関数内の結果をreturnで返さないでね。非同期処理の中の値をreturnで返してもundefinedしか返ってきません。)、結果を.thenと受け取る事が可能です。.then()内ではコールバックを書いて続けて次の処理を書いてゆきます。さらにpromiseオブジェクトを返す関数を.then()のコールバック関数内でreturnで返す事によりさらに続けて非同期処理を同期的に実行します。returnで返されたpromiseの実行結果は続けて.then()とメソッドチェーンでつなげてゆきます。なので続けて.thenとコールバックを書いてゆくことによりネストの浅い見やすいコードが実現できます。

関数内でpromiseのオブジェクト自体を返す必要があるので実行結果を次の関数に渡す場合はどうするのか?という疑問が出てくると思います。これはresolveというpromiseの第一引数のメソッドに値を渡せば値をそのまま返してくれます。返ってきた値はthen内のコールバック関数が返り値として受け取ります。アロー関数の省略記述を避けてもう少しわかり易く書きます。

それぞれpromise内のresolveに渡した結果をコールバックの返り値としてpersonをthen引数として受け取ってconsole.logで表示しています。

省略していましたがpromiseの第二引数で続く非同期処理を拒否できます。第二引数rejectに拒否の理由、または値を渡し、promiseのメソッドチェーンの各関数内rejectの値はcatchで受け取れます。

isNanでtrueを返した場合はrejectでエラーを返します。エラー後の処理はメソッドチェーンの最後にcatchでコールバックで受け取れます。非同期関数内のエラーををまとめて一括管理が可能です。try,catchのようにrejectされた場合も起きてない場合も最後に同一の処理を実行したい場合はcatchに続けてfinallyでコールバック関数を実行できます。

早足になりましたがざっくばらんな非同期処理の概要になります。Adobe Extensionであれこれやっているうちにソケット通信でメールを飛ばすとか、jsonデータをサーバー に送るとかやりたくなると思います。その時にいろんな障害にぶつかると思いますがこの非同期通信は間違いなくその一つになるでしょう。Extensionと長く付き合う場合は必ず理解する必要になるとはずです。

Beer 寄付してサイトを応援する。