[Firebase] Cloud Functions での Realtime Database 操作が Promise 地獄に陥ったので async/await に書き換えてみた
Promise が難しい
Promise って難しくないですか? できれば認めたくなかったですけど、僕には Rx も Promise もとても難しいです……。一日中 Rx のデータの流れを書いている仕事ならまだやれそうなんですが、アプリケーションを作る頭と切り替えながら使うのが、とても難しいです。
会社のすごい人たちは Promise も普通の Function もプリミティブな Number も変わらないでしょみたいな顔して使ってたりしますけど、僕には無理みたいです。
というわけで、

こういうコードを一度書くまではなんとかいいんですけど、さらに別のデータの読み込みを追加したり、別の通知も送ろうって思って新しい非同期処理が増えたり、どれとどれが並列で行けるはずだからと高速化を考えたり、あるいは Database 側の持ち方を工夫してネスト減らせるぞってなったときにも、まあまずテストで死にそうになる始末です。
そもそもが、うまく構造化できない……。
async/await で Promise を基盤にしちゃって見ないことにする
というわけで async/await で Promise を基盤にしてしまい、通常のコーディングでは見なくていいことにしたいと思いました。ずっとそうしたいと思っていたんですけど、もっと辛いことになったらどうしようって怖がっていたところがありました。
でも、やってみたら案外簡単でした。
もともと flow を使っていて babel で変換をかけていたので、設定も簡単でした。
まずはコードから。

やだ!なにこれ!最高!超やだー
ほとんど同期処理の連なりに見える!
さらに嬉しかったのが、テストをほとんど変更しなくてよかったことでした。外側から見れば async function を実行した戻り値はただの Promise 。 await はただの Promise の resolve 待ちです。 once を色々モックしていたんですが、そのまま動いちゃいました。
手順
まず、現時点で Cloud Functions の node のバージョンは v6.11.1 ですので用意します。
自分は node のバージョン管理に n 。 npm のかわりに yarn を使っています。
変換は babel と transform-async-to-generator プラグインでやりました。 babel のインストールからやるとこんな感じでしょうか。
$ yarn add --dev babel-cli
$ yarn add --dev babel-plugin-transform-async-to-generator.babelrc はこんな感じです。
{
"plugins": ["transform-async-to-generator"],
"ignore": [
"node_modules"
]
}あとは babel を実行して変換します。
$ babel src -d functions --ignore node_modulesいまの仕事ではまだ make とか gulp とか使わず npm の scripts でいいかなあくらいのテンションでやってます。 package.json をこんな感じにして
{
"scripts": {
"build": "babel src -d functions --ignore node_modules && cp src/*.json functions/ && cp -r src/node_modules functions/",
"deploy": "npm run build && firebase deploy"
},
"devDependencies": {
"babel-cli": "^6.26.0",
"babel-plugin-transform-async-to-generator": "^6.24.1"
}
}実行は
$ yarn deployです。仕事なら build の前にテストを入れてます。
はー、なんかもうちょっと頑張れそうです……。
