Caution

お使いのブラウザはJavaScriptが実行できない状態になっております。
当サイトはWebプログラミングの情報サイトの為、
JavaScriptが実行できない環境では正しいコンテンツが提供出来ません。
JavaScriptが実行可能な状態でご閲覧頂くようお願い申し上げます。

Swift辞典

  1. トップページ
  2. Swift辞典
  3. async / await の基本

async / await の基本

SwiftのSwift Concurrency(Swift 5.5+)では、『async』と『await』を使って非同期処理を同期的なコードのように記述できます。コールバックのネストを解消します。

構文
// async 関数の定義
func 関数名() async -> 型 {
    // 非同期処理
}

// エラーを投げる async 関数
func 関数名() async throws -> 型 {
    // 非同期処理
}

// await で非同期関数を呼び出す
let result = await 関数名()
let data   = try await 非同期関数名()

// async let: 並列実行
async let a = 非同期関数A()
async let b = 非同期関数B()
let (resultA, resultB) = await (a, b)
構文一覧
構文概要
async func非同期関数を定義します。
await 式非同期関数の完了を待ちます。
async throws func非同期かつエラーを投げる関数を定義します。
try await 式非同期かつエラーを投げる関数を呼び出します。
async let複数の非同期処理を並列実行します。
Task { }非同期コンテキストでコードを実行するタスクを作成します。
サンプルコード
import Foundation

// async throws 関数の定義
func fetchUserName(id: Int) async throws -> String {
    // 実際の実装では URLSession.shared.data(from:) などを使う
    // ここではシミュレーション
    try await Task.sleep(nanoseconds: 100_000_000)  // 0.1秒待機
    let users = [1: "Alice", 2: "Bob", 3: "Carol"]
    guard let name = users[id] else {
        throw URLError(.badURL)
    }
    return name
}

func fetchScore(name: String) async -> Int {
    try? await Task.sleep(nanoseconds: 50_000_000)
    return name.count * 10
}

// async 関数は Task から呼び出す
Task {
    // 順番に実行
    do {
        let name = try await fetchUserName(id: 1)
        print("名前: \(name)")

        let score = await fetchScore(name: name)
        print("スコア: \(score)")
    } catch {
        print("エラー: \(error)")
    }

    // async let で並列実行
    async let name2 = fetchUserName(id: 2)
    async let name3 = fetchUserName(id: 3)

    do {
        let (n2, n3) = try await (name2, name3)
        print("並列取得: \(n2), \(n3)")
    } catch {
        print("エラー: \(error)")
    }
}

// 同期コードから Task を使って非同期処理を開始
print("非同期処理を開始しました")
概要

Swift Concurrency の async/await を使うことで、コールバックのネスト(コールバック地獄)を解消し、直線的で読みやすい非同期コードを書けます。

『async let』を使うと複数の非同期処理を並列に開始し、全ての結果を await でまとめて待機できます。await は現在のスレッドをブロックせず、処理を一時停止してスレッドを解放します。再開時に同じスレッドに戻る保証はありません(@MainActor を使うと UI スレッドに戻れます)。

Task と TaskGroup についてはTask / TaskGroup / async letを参照してください。

記事の間違いや著作権の侵害等ございましたらお手数ですがまでご連絡頂ければ幸いです。