Contents 非表示
async letとは
async let = 非同期処理を「同時に始めて、後でまとめて受け取れる」仕組み。
Swift Concurrencyを使えば、複数の非同期処理を同時に実行して、あとで結果をまとめて取得するのも楽。
async let のメリット
- 同時に複数の処理を走らせられる(並列処理)
- コードがシンプル、読みやすい
- 順番に依存しない処理にGood
サンプルコードでざっくり学ぶ
3つのリクエストを同時に実行する
import SwiftUI
struct DummyUser: Codable, Identifiable {
let id: Int
let name: String
}
struct DummyPost: Codable, Identifiable {
let id: Int
let userId: Int
let title: String
}
struct DummyComment: Codable, Identifiable {
let id: Int
let postId: Int
let body: String
}
struct HomeView: View {
@State private var user: DummyUser?
@State private var posts: [DummyPost] = []
@State private var comments: [DummyComment] = []
@State private var isLoading = false
@State private var errorMessage: String?
var body: some View {
VStack(spacing: 16) {
if isLoading {
ProgressView("Loading...")
} else {
if let user = user {
Text("User: \(user.name)")
}
Text("📝 投稿数: \(posts.count)")
Text("💬 コメント数: \(comments.count)")
Button("Fetch Data") {
Task {
await fetchAllData()
}
}
}
if let errorMessage = errorMessage {
Text("Error: \(errorMessage)")
.foregroundColor(.red)
.padding()
}
}
.padding()
}
// 本番ではアーキテクチャに沿ってViewModel等で処理しましょう、今回はわかりやすさ重視
private func fetchAllData() async {
isLoading = true
do {
// Point: async letは宣言時点で非同期処理を開始するため、複数のAPI呼び出しを同時に行える
async let user = fetchUser()
async let posts = fetchPosts()
async let comments = fetchComments()
// 結果が返る順番は保証されないが、全ての非同期処理が完了するまで待機する、順番も制御したい場合はTaskGroupを使用する(これは次章以降に続く)
self.user = try await user
self.posts = try await posts
self.comments = try await comments
isLoading = false
} catch {
// 非同期リクエストのうち一つでも失敗した場合、catchブロックが実行される
isLoading = false
errorMessage = "データの取得に失敗しました: \(error.localizedDescription)"
}
}
private func fetchUser() async throws -> DummyUser {
let url = URL(string: "https://jsonplaceholder.typicode.com/users/1")!
let (data, _) = try await URLSession.shared.data(from: url)
return try JSONDecoder().decode(DummyUser.self, from: data)
}
private func fetchPosts() async throws -> [DummyPost] {
let randomUserNumber = Int.random(in: 1...10)
let url = URL(string: "https://jsonplaceholder.typicode.com/posts?userId=1")!
let (data, _) = try await URLSession.shared.data(from: url)
return try JSONDecoder().decode([DummyPost].self, from: data)
}
private func fetchComments() async throws -> [DummyComment] {
let url = URL(string: "https://jsonplaceholder.typicode.com/comments?postId=1")!
let (data, _) = try await URLSession.shared.data(from: url)
return try JSONDecoder().decode([DummyComment].self, from: data)
}
}
まとめ
async let
を使えば、複数の非同期処理を同時にスタートできる- 処理が終わるまで
try await
で後からまとめて結果を取得 async let
は宣言した瞬間に実行される(=即時スタート)- 順番に依存しない処理(ユーザー取得→投稿取得→コメント取得みたいな)に最適
- ただし、どれか1つが失敗したら他もキャンセルされる点には注意
次回はTaskGroupで大量並列をやっていきましょう。
