0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

finally で async ジェネレータの反復完了時、中断時、エラー発生時の全てで処理を行う

Last updated at Posted at 2020-06-24

DB やファイルなどからデータをたくさん取り出して
それぞれのデータに対して何かしたい場合は多くあると思います

async function* readLines() {
  console.log('ファイル開く処理')
  for (let i = 1; i <= 5; ++i)
    yield { textContent: `${i} 番目の行` }
  console.log('ファイル閉じる処理')
}
for await (const line of readLines()) {
  console.log(line.textContent)
}
// ファイル開く処理
// 1 番目の行
// 2 番目の行
// 3 番目の行
// 4 番目の行
// 5 番目の行
// ファイル閉じる処理

解決すべき課題

上記の readLines には問題があります

async function* readLines() {
  console.log('ファイル開く処理')
  for (let i = 1; i <= 5; ++i)
    yield { textContent: `${i} 番目の行` }
  console.log('ファイル閉じる処理')
}
let tmp = 0
for await (const line of readLines()) {
  console.log(line.textContent)
  if (++tmp >= 3) break
}
// ファイル開く処理
// 1 番目の行
// 2 番目の行
// 3 番目の行

途中で break すると ファイル閉じる処理 が実行されません

あるいは途中でエラーが起こると…

async function* readLines() {
  console.log('ファイル開く処理')
  for (let i = 1; i <= 5; ++i) {
    if (3 === i) throw new Error('何かエラー')
    yield { textContent: `${i} 番目の行` }
  }
  console.log('ファイル閉じる処理')
}
for await (const line of readLines()) {
  console.log(line.textContent)
}
// ファイル開く処理
// 1 番目の行
// 2 番目の行
// Error: 何かエラー

こちらでも ファイル閉じる処理 が実行されません

finally を使う

反復完了時、または中断時、そしてエラー発生時の全てで処理を行うには finally が使えます

async function* readLines() {
  console.log('ファイル開く処理')
  try {
    for (let i = 1; i <= 5; ++i)
      yield { textContent: `${i} 番目の行` }
  } finally {
    console.log('ファイル閉じる処理')
  }
}
let tmp = 0
for await (const line of readLines()) {
  console.log(line.textContent)
  if (++tmp >= 3) break
}
// ファイル開く処理
// 1 番目の行
// 2 番目の行
// 3 番目の行
// ファイル閉じる処理
async function* readLines() {
  console.log('ファイル開く処理')
  try {
    for (let i = 1; i <= 5; ++i) {
      if (3 === i) throw new Error('何かエラー')
      yield { textContent: `${i} 番目の行` }
    }
  } finally {
    console.log('ファイル閉じる処理')
  }
}
for await (const line of readLines()) {
  console.log(line.textContent)
}
// ファイル開く処理
// 1 番目の行
// 2 番目の行
// ファイル閉じる処理
// Error: 何かエラー
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?