JavaScriptから学ぶSwiftで新しく対応したasync、await

Swiftでasyncとawait機能が対応した。
自分自身Swift以外の言語の素養がなく、asyncとawaitとはなんぞやというところから勉強したのでその記録
async、awaitの学習教材としてJavaScriptの言語仕様を見ている

# 前提知識として、JavaScriptでのasync await

## Promise型　
非同期処理の戻り値であり、非同期が完了するまで、その実態はundefinedになる。

戻り値が返ってきたら、その戻り値がラップされた型となる。戻り値が返ってきたタイミングで自身のthen()メソッドを呼ぶ

```jsx
getDate()
.then(function(data) {
 
    return getYear(data)
 
}) .then(function(year) {
 
    return getSomething(year)
 
}) .then(function(item) {
 
    getAnotherThing(item)
 
})
```

## async 
非同期の戻り値(Promise)が返ってくる (asyncで呼ばれるメソッドは基本バックグラウンドで実行される)

```jsx
async function(){
	getDate()
	.then(function(data) {
 
	    return getYear(data)
 
	}) .then(function(year) {
 
	    return getSomething(year)
 
	}) .then(function(item) {
 
	    getAnotherThing(item)
 
	})
}.then(function(data){
  // 戻り値がPromiseなので更なるthenを実行することもできる
})
```

## await 
asyncな処理（ Promiseが返ってくるような処理）において、Promiseの値が決定するまでその場で待機してくれる

```jsx
function myPromise(num) {
  return new Promise(function(resolve) {
 
    setTimeout(function() { resolve(num * num) }, 3000)
 
  })
}

async function myAsync() {
		  // ここで約3秒待機する
    const result = await myPromise(10);
		 // ここは実行されない
    console.log(result);
 
}
 
myAsync();
```

## awaitの使い所　
then()で繋げなくて良くなる

```jsx
myPromise(10).then(function(data) {
 
    console.log(data);
    return myPromise(100)
 
}).then(function(data) {
 
    console.log(data);
    return myPromise(1000)
 
}).then(function(data) {
 
    console.log(data);
 
})

// これをawaitを使うと下のようにかける！

async function myAsyncAll() {
  
    console.log(await myPromise(10));
    console.log(await myPromise(100));
    console.log(await myPromise(1000));
  
}
 
myAsyncAll();
```

# Swiftで
だいたい一緒　asyncのなかでUIを触りたいときはMainActor.runでメインスレッドでの実行を明示的にする

```swift
enum CustomError:Error {
    case badURL
    case badImage
}

func fetchData(urlString:String) async -> Result<CustomModel,CustomError>{
    let request = URLRequest(url: URL(string: urlString)!)
    guard let (data, response) = try? await URLSession.shared.data(for: request, delegate: nil),(response as? HTTPURLResponse)?.statusCode == 200 else {
        return .failure(.badURL)
    }
    let model = convertDataToModel(data: data)
    return .success(model)
}

struct CustomModel{
    
}

func convertDataToModel(data:Data)->CustomModel{
    return .init()
}

// 一回のみの実行　（fetchDataの処理が完了したら、switch文の中身を実行）
func executeFetchData() async{
    switch await fetchData(urlString: "http://example.com"){
    case .success(let model):
        print(model)
        
        await MainActor.run{ [weak self] in
            self?.label = model.text
        }
    case .failure(let error):
        print(error)
    }
}

// 複数回の実行
func executeMultipleFetchData() async {
    switch await fetchData(urlString: "http://example.com"){
    case .success(let model):
        print(model)
        await MainActor.run{ [weak self] in
            tableViewSectionTitle[0] = model.text
        }
        switch await fetchData(urlString: "http://example2.com"){
        case .success(let model2):
            await MainActor.run{ [weak self] in
                tableViewSectionTitle[1] = model2.text
            }
        case .failure(let error):
            print(error)
        }
    case .failure(let error):
        print(error)
    }
}
```