非同期なメソッドを直列に動作させる書き方

はじめに

昨日npmを作成していて、非同期処理メソッドを狙い通りに動かすことができずに苦しんだ。 特に、3つ以上のメソッドが出てくる場合にどう記述したらいいのか混乱した。

そこで、Promiseおよびasync/awaitの復習をした。

三つ以上の非同期処理メソッドを直列に動作させるためのasync/awaitの書き方

例として以下のメソッドを用意した。

const sample1 = () => {
  setTimeout(
    () => { console.log('サンプル1') }, 2000
  )
}
const sample2 = () => {
  setTimeout(
    () => { console.log('サンプル2') }, 1500
  )
}
const sample3 = () => {
  setTimeout(
    () => { console.log('サンプル3') }, 1000
  )
}

これらのメソッドは非同期処理のため、

sample1()
sample2()
sample3()

と書いても、実行してみると、

サンプル3
サンプル2
サンプル1

と逆になる。

これを数字順になるようにPromiseを使って書くと、

const sample1 = () => {
  const promise = new Promise((resolve) => {
    setTimeout(
      () => {
        console.log('サンプル1')
        resolve()
      }, 2000)
  })
  return promise
}

const sample2 = () => {
  const promise = new Promise((resolve) => {
    setTimeout(
      () => {
        console.log('サンプル2')
        resolve()
      }, 1500)
  })
  return promise
}

const sample3 = () => {
  const promise = new Promise((resolve) => {
    setTimeout(
      () => {
        console.log('サンプル3')
        resolve()
      }, 1000)
  })
  return promise
}

sample1()
  .then(() => sample2())
  .then(() => sample3())

こうなる。

「処理したい関数」をPromiseオブジェクトで包んで、それをさらに関数でラッピング。

ラッピングした関数をthen()チェーンで直列に繋げるといった感じ。

これらをさらにasync/awaitを使って書くと...

const sampleSync = async () => {
  await sample1()
  await sample2()
  await sample3()
}

sampleSync()

こうなる。

asyncがついた関数内で、awaitがついた関数があると、その関数が終わるまで次に処理が進まないため、上から順に関数が実行される。