Swiftでasyncとawait機能が対応した。
自分自身Swift以外の言語の素養がなく、asyncとawaitとはなんぞやというところから勉強したのでその記録
async、awaitの学習教材としてJavaScriptの言語仕様を見ている
前提知識として、JavaScriptでのasync await
Promise型
非同期処理の戻り値であり、非同期が完了するまで、その実態はundefinedになる。
戻り値が返ってきたら、その戻り値がラップされた型となる。戻り値が返ってきたタイミングで自身のthen()メソッドを呼ぶ
getDate()
.then(function(data) {
return getYear(data)
}) .then(function(year) {
return getSomething(year)
}) .then(function(item) {
getAnotherThing(item)
})
async
非同期の戻り値(Promise)が返ってくる (asyncで呼ばれるメソッドは基本バックグラウンドで実行される)
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の値が決定するまでその場で待機してくれる
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()で繋げなくて良くなる
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でメインスレッドでの実行を明示的にする
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)
}
}