Promiseとasyncとawaitに関する理解
って直感的に難しいよね、慣れてないと。
まぁ慣れていても
Promiseは非同期実行を同期実行っぽくしてくれるやつ
asyncはPromiseを返す関数を返す
awaitはasyncなFuncのなかで非同期実行を同期実行っぽく表現できる
くらいのノリしかなかったりする。
それでいいならいいんだが、自分としては「結構大事な処理なところなのに、動きとその成り立ちについて理解していない」のでなんか気持ち悪い。
いや、ちょっとカッコつけていったな。
もっと正直に言えば魔法のように見えすぎて怖い、って感じかな。
自分は正しく使えていないんじゃないか、、、理解できていないんじゃないか、、、みたいな。
ノリに乗っていれば後述するが、「ポルターガイスト」のような恐怖だ。
ちょっと面倒くさい脇道だが、ここでいう「正しい理解」という言葉もそんなに誠実で力強いものじゃない。
#! /bin/bash がShebangと呼ばれていて、インタプリタを指定するものだ、
と言われれば「あれが魔法じゃなくなる」という類の、そんなものだ。
今晩もぐっすり眠れるように、程度の意味しかない。
まぁすごい大きいんだけどね、それって。
さて、Promiseだが。
俺の中でPromiseのようなわかりづらさのことを、
「ポルターガイスト」
と(心のなかで)呼んでいて、つまりこれは前述の「魔法」と同じ系のわかりづらさのことを指している。
ポルターガイスト現象のような恐怖体験を、なんだかありがたい人から「ポルターガイスト現象だ」と定義してもらった瞬間に「なぁんだポルターガイストだったのか」
といってぐっすり眠れるタイプの人と、むしろそこから真の恐怖が始まる人が世界にいるんだけど、俺は後者なんですね。
今までは勝手に物が動いてても気にもしなかったのに、「ポルターガイストだって!?なにそれ!」って、突然気になりだしちゃう人なんですね。
この類の恐怖は、「ポルターガイストって一体何なんだろう」と考え出すところに複雑さの源泉がある。
もっと言ってしまえば、ポルターガイストによって物が勝手に動いたりするんだ、という思い込みが、
ポルターガイストが何者なのかを考える原点になってしまい、きっとまだみぬ心霊体験なんだとなって、「この家の前の住人がまさか、、、」とか考え出して、無限の可能性について議論してしまうことが問題なんだと思っている。
本当の問題は、「なぜ物が動いたか」であって、「ポルターガイスト」なんて言葉や、それによって想起される不必要な恐怖イメージはマジで忘れていいんですよね。
で、Promiseもそれと同じだよ、という話。
Promiseを「非同期と同期」とか、「resolveとrejectがあって、thenがあるんだ」とか、そういう結果をみて、Promiseの幻影と戦い出すと無茶苦茶強いんですよ、こいつ。
ということで、素朴に問題点を「コールバック地獄」に戻すのが吉なんですねきっと。
ノンブロッキングI/Oな言語で「2つのファイルに書かれた数字を足し上げる」というとてもシンプルなことをやろうとする。
PHP大学出身の人々ならきっとこういうイメージをする
code:js
var sum = 0
var a = readFile('a.txt')
var b = readFile('b.txt')
sum = a + b
console.log(sum)
ここに幽霊は存在しない。これが動けば皆ぐっすり眠ることだろうが、そうならない。
理由は当然I/O非同期なので、a.txtやb.txtは「適当に並行処理」されてしまい、いつ完了してa,bに代入されるかなんかわからんのです。
ということで人はこれをコールバックでクリアしようとしたわけです。
readFile('a.txt')のあとにやろうとしていた処理を、事前にreadFileに教えてあげればよいんだ、というシンプルな回答です。
code:js
var sum = 0
readFile('a.txt', (a) => {
readFile('b.txt', (b) => {
sum = a + b
console.log(sum)
})
})
これは色々つらい。
見た目もつらいけど、もっと宣言的に書けないか、と思うわけです。
普通に考えたら、readFileが終わるまでまって、その結果をうければいい、となりますね。
しかし、言語仕様上それはコールバックじゃないとできない。
となるともう、「どうやってコールバックをうまく渡すか」を考えればいいとなります。