Make it to make it

いろいろ作ってアウトプットするブログ

async/await再入門

asyncファンクション

asyncファンクションが通常のファンクションと何が違うかは、以下の2つの例を見ればわかる。

function hello(ms) {
  return new Promise(resolve => setTimeout(() => {
    resolve('Hello from the other side!')
  }, ms))
}

console.log(hello(1000))
async function hello(ms) {
  return new Promise(resolve => setTimeout(() => {
    resolve('Hello from the other side!')
  }, ms))
}

console.log(hello(1000))

結果はasyncを付けても付けなくても変わらず、ともにpromiseをreturnする。つまり、promise返すファンクションでは、asyncは何も作用しない。

では、ほとんどのpromiseを返さないファンクションではどうか?

function say(message) {
  return message
}

console.log(say('Greeting!'))
async function say(message) {
  return message
}

console.log(say('Greeting!'))

通常のファンクションは当然ながらGreeting!を返却するが、asyncファンクションはpromiseオブジェクトを返す。

つまり、通常のファクションにasyncを足すと、promiseオブジェクトにwrapされるかたちで返却される。

await演算子

awaitが使われるのはasyncファンクションの中だけである。

awaitの役割は、promiseを渡されたときにそれがresolveするまで処理を止めることだ。これはpromise.then()と似ているが、awaitの場合は別のファンクションを用意して処理結果をハンドルする必要がなく、ただ結果が返されるというシンプルなものだ。

それでは、promiseでないものに対してawaitを記述するとどうなるかというと、non-promiseにも使えるものの、promise.then()のように、他のスクリプトが処理された後に処理される。

document.querySelector('.btn').addEventListener('click', async () => {
  const user = await getUser('mrsung')
  const weather = await getWeather(user.location)

  updateUI({
    user,
    weather
  })
})

エラーハンドリング

async/awaitを記述した際にエラーをどのようにハンドリングするのかというと、try/catchブロックで処理するのが通例である。

document.querySelector('.btn').addEventListener('click', async () => {
  try {
    const user = await getUser('mrsung')
    const weather = await getWeather(user.location)

    updateUI({
      user,
      weather
    })
  } catch (e) {
    showError(e)
  }
})