Article

Writing Failable Asynchronous APIs 失敗できる非同期APIを記述する

Vend results as part of an API when you can’t return errors synchronously. 結果をAPIの一部として提供します、あなたがエラーを同期的に返すことができない場合に。

Overview 概要

When writing a function, method, or other API that might fail, you use the throws keyword on the declaration to indicate that the API call can throw an error. However, you can’t use the throws keyword to model APIs that return asynchronously. Instead, use the Result enumeration to capture information about whether an asychronous call succeeds or fails, and use the associated values for the Result.success(_:) and Result.failure(_:) cases to carry information about the result of the call. 失敗するかもしれない関数、メソッド、または他のAPIを書いている時、あなたはthrowsキーワードをその宣言上で使うことで、そのAPI呼び出しがエラーをスローできることを指し示します。しかしながら、あなたはthrowsキーワードを使うことで、非同期に返るAPIをこしらえることはできません。代わりに、Result列挙を使うことで、非同期の呼び出しが成功するか失敗するかについての情報をキャプチャしてください、そしてResult.success(_:)Result.failure(_:)ケース節に対する関連値を使うことで、呼び出しの結果についての情報を運んでください。

Return Result Instances Asynchronously 結果インスタンスを非同期に返す

The following example models an asynchronous source of random numbers. The fetchRemoteRandomNumber(completion:) method returns Void synchronously, and asynchronously calls a completion handler with a Result<Int, EntropyError> instance that contains either a random result or information about the failure. 以下の例は、無作為数の非同期ソースをこしらえます。fetchRemoteRandomNumber(completion:)メソッドは、Voidを同期的に返します、そして非同期に完了ハンドラをResult<Int, EntropyError>インスタンスとともに呼び出します、それはある無作為な結果またはその失敗についての情報のどちらかを含みます。


let queue = DispatchQueue(label: "com.example.queue")


enum EntropyError: Error {
    case entropyDepleted
}


struct AsyncRandomGenerator {
    static let entropyLimit = 5
    var count = 0
    
    mutating func fetchRemoteRandomNumber(
        completion: @escaping (Result<Int, EntropyError>) -> Void
    ) {
        let result: Result<Int, EntropyError>
        if count < AsyncRandomGenerator.entropyLimit {
            // Produce numbers until reaching the entropy limit.
            result = .success(Int.random(in: 1...100))
        } else {
            // Supply a failure reason when the caller hits the limit.
            result = .failure(.entropyDepleted)
        }
        
        count += 1
        
        // Delay to simulate an asynchronous source of entropy.
        queue.asyncAfter(deadline: .now() + 2) {
            completion(result)
        }
    }
}

Users of your remote random number generator can decide how to handle both the success and failure cases: あなたの遠隔無作為数生成子のユーザは、成功および失敗の場合の両方をどのように取り扱うか決定できます:


var generator = AsyncRandomGenerator()


// Request one more number than the limit to trigger a failure.
(0..<AsyncRandomGenerator.entropyLimit + 1).forEach { _ in
    generator.fetchRemoteRandomNumber { result in
        switch result {
        case .success(let number):
            print(number)
        case .failure(let error):
            print("Source of randomness failed: \(error)")
        }
    }
}


print("Waiting on some numbers.")


dispatchMain()
/* Prints:
success(29)
success(46)
success(85)
success(39)
success(84)
Source of randomness failed: entropyDepleted
*/

See Also 参照

Representing a Result 結果の表現