await と初期化前アクセスエラー
思わぬところで初期化前の変数にアクセスするエラーが出てました
簡単に書くとだいたいこういう感じになってました

const setup = async () => {
foo.on("bar", () => {
console.log(value)
})

const value = await getValue()
}

リスナの設定など外部からアクセスできる関数を設定したあとに await で待機します
await の完了より前に関数が呼び出されると value がまだ初期化されていないのでアクセスしたタイミングでエラーです
同期的だと気にしなくてよかった順番でも 非同期化すると順番を考慮しないとこういうケースがありますね

単純に value への代入を先に持ってくることもできますが イベントを逃すと困るところでは await を待たずに先にリスナを設定しておきたいケースもあります
そうなると一旦 value を先に初期化しておかないといけないのでこうなります

const setup = async () => {
let value = null

foo.on("bar", () => {
console.log(value)
})

value = await getValue()
}

再代入が必要になるので let にせざるを得ないのがいまいちです
後で実行する処理の書き方
今すぐに実行せずに後になってから実行したい処理の書き方で
後で実行する部分を関数にまとめて その関数をどこかに渡しておいて 実行するタイミングで呼び出すのと 「await xxx」 みたいのを書いておいて その後ろに後で実行する部分を書いて実行するタイミングで xxx の Promise を resolve するの
どっちがいいか迷ってて 処理を関数にまとめて渡すほうがわかりやすいかなって気はしてたけど コールバック関数と await と考えたら await のほうが良い気もしてきた

「1 秒後に実行」で考えてみたら await の方かなぁ

function a() {
something()

setTimeout(() => {
something2()
}, 1000)
}

async function b() {
something()

await new Promise(r => setTimeout(r, 1000))

something2()
}

でも 複雑になってくるとコールバック関数のほうかも

const items = []
setInterval(() => {
items.shift()?.()
}, 5000)

function a() {
something()

items.push(() => something2())
}

async function b() {
something()

const promise = new Promise(r => items.push(r))
await promise

something2()
}
async の catch
非同期でエラーを起こす関数を用意
1 秒後に Promise を reject

async function causeAsyncError() {
return new Promise((ok, ng) => setTimeout(ng, 1000))
}

try の中で呼び出しても非同期なものは catch されない

async function f1() {
try {
causeAsyncError()
} catch (err) {
console.log("catch")
}
}

f1()
// uncaught error

返り値を await すると catch される

async function f2() {
try {
await causeAsyncError()
} catch (err) {
console.log("catch")
}
}

f2()
// catch

f1 を呼び出す側で await しても効果なし

try {
await f1()
} catch (err) {
cosnole.log("catch")
}
// uncaught error

f1 の Promise は causeAsyncError の結果を待たずに解決される
ループの中などで await させたくない場合は個々に catch メソッド使うことになる

async function f1_() {
try {
causeAsyncError().catch(e => console.log("catch"))
} catch (err) {
console.log("catch")
}
}

f1_()
// catcch

then と await
fetch するとき

const obj = await fetch("http://example.com/").then(e => e.json())

って書くとせっかく await あるんだから then じゃなくて await に揃えたくなる

でも await 使うと

const obj = await (await fetch("http://example.co.jp/")).json()

になる
見づらい
括弧があるのが嫌

でも優先順位的に括弧は必要
ならメソッドにすればできる?
関数受け取って 中で await した結果を受け取った関数に入れて実行するとか

const obj = await fetch("http://example.net/").await(e => e.json())

あれ これ then だ
しかも一文字長くなってる

変なことせず then でいいところは then にしよう