LoginSignup
12
6

【TCA】EffectTaskのtask/run/fireAndForgetメソッドの使い分け

Last updated at Posted at 2023-03-04

0.53.0よりtaskfireAndForgetはSoft-Deprecatedとなりました
今後はrunのみを使いましょう

Reducerで非同期処理を実行するためのツールとして、EffectTaskには3つのstaticメソッドが用意されています。

使い分けのポイントとしては以下のようになります。

メソッド 用途
task(priority:operation:catch:) 1つのActionをSendする
run(priority:operation:catch:) 0または1つ以上のActionをSendする
fireAndforget(priority:_:) ActionをSendしない

task(priority:operation:catch:)

taskでは、以下のようにActionをreturnする必要があります。
returnする前に、複数の非同期処理を実行可能です。

return .task {
  try await operation1()
  try await operation2()
  return await .fetchResponse(TaskResult {
    try await self.fetch()
  })
}

run(priority:operation:catch:)

runの使いどころは主に2つあります。
一つは、for-await-inでAsyncSequenceを処理するケースです。

return .run { send in
  for await newValue in self.listen() {
    await send(.updated(newValue))
  }
}

もう一つは、条件によってActionを送信しなかったり、あるいは複数送信するようなロジックを持つケースです。

return .run { send in
  guard ... else { return }  // 何もしない
  await send(
    .fetchResponse(TaskResult {
      try await self.fetch()
    })
  )
  // もっとActionをsendすることもできる
}

isowordsでは、withThrowingTaskGroupを使って複数の非同期処理を並列実行させるような使い方もしていました。

fireAndforget(priority:_:)

非同期処理を実行するだけでActionを送信しない場合は、fireAndforgetを使います。

return .fireAndForget {
  try await operation1()
  try await operation2()
}

エラーのキャッチについて

taskruncatchという引数にエラーを受け取るクロージャを指定できます。
operationクロージャでエラーがスローされた場合、catchクロージャが実行されます。

return .task {
  try await operation()  // ここでエラーがスローされるとする
  return await .fetchResponse(TaskResult {
    try await self.fetch()
  })
} catch: {  // ここでキャッチ
  return .operationFailed  // エラーが発生したことを通知するActionをSendする
}

あるいは、do-catchでエラーをキャッチします。

return .task {
  do {
    try await operation()
    return await .fetchResponse(TaskResult {
      try await self.fetch()
    })
  } catch {
    return .operationFailed
  }
}

taskおよびrunでエラーをキャッチしなかった場合、以下のようなワーニングが出力されます。

An "EffectTask.task" returned from "SomeFeature.swift:58" threw an unhandled error. …

    SomeFeature.OperationError()

All non-cancellation errors must be explicitly handled via the "catch" parameter on "EffectTask.task", or via a "do" block.

なお、fireAndForgetはエラーがスローされても無視され、ワーニングも出力されません。

12
6
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
12
6