444
Apple đã giới thiệu cho cộng đồng dev iOS về Swift 5.5, trong đó có sự cập nhật rất là lớn. Đó là về bất đồng bộ, với async await
Để xem async / await giúp ngôn ngữ như thế nào, sẽ hữu ích khi xem cách chúng tôi đã giải quyết vấn đề tương tự trước đây.
Một ví dụ về networking trước khi async await được update
class SeverConnection {
let defaultSession = URLSession(configuration: URLSessionConfiguration.default)
var dataTask: URLSessionDataTask?
var downloadTask: URLSessionDownloadTask?
var uploadTask: URLSessionUploadTask?
}
extension SeverConnection {
func fetchAPIFromURL(_ url: String, completion: @escaping (String?, Error?) -> Void) {
guard let url = URL(string: url) else {
completion(nil, SeverConnectionError.badURL)
return
}
dataTask = defaultSession.dataTask(with: url, completionHandler: { (data, response, error) in
if let error = error {
completion(nil, SeverConnectionError.errorWithDataTask)
return
}
guard let httpResponse = response as? HTTPURLResponse,
(200...299).contains(httpResponse.statusCode) else {
completion(nil, SeverConnectionError.badResponse)
return
}
guard let data = data else { return }
let dataString = String(data: data, encoding: .utf8)
completion(dataString, nil)
})
dataTask?.resume()
}
}
khi sử dụng:
private func fetchListData() {
let urlString = "https://vapor-mock.herokuapp.com/pic_dic.json"
severConnection.fetchAPIFromURL(urlString) { [weak self] (data, error) in
guard let self = self else {
return
}
if let error = error {
print(error)
}
if let data = data {
self.convertData(data)
}
}
}
private func convertData(_ data: String) {
let responseData = Data(data.utf8)
let decoder = JSONDecoder()
var responseImageData: [ImageData]?
do {
responseImageData = try decoder.decode([ImageData].self, from: responseData)
infoImages = responseImageData
DispatchQueue.main.async {
self.mainTableView.reloadData()
}
} catch {
print("Error decoding imageData: \(error)")
}
}
Còn với async await
class FetchAPITask {
static let shared = FetchAPITask()
func fetchAPI<D: Decodable>(url: URL) async throws -> D {
let task = Task { () -> D in
try await fetchAndDecode(url: url)
}
return try await task.value
}
func fetchAPIGroup<D: Decodable>(urls: [URL]) async throws -> [D] {
try await withThrowingTaskGroup(of: D.self) { (group) in
for url in urls {
group.async { try await self.fetchAndDecode(url: url) }
}
var results = [D]()
for try await result in group {
results.append(result)
}
return results
}
}
func fetchAndDecode<D: Decodable>(url: URL) async throws -> D {
let data = try await URLSession.shared.fetchData(with: url)
let decodedData = try JSONDecoder().decode(D.self, from: data)
return decodedData
}
}
khi sử dụng:
func fetchAllAPI() async {
do {
if let url = url {
let datas: [ImageData] = try await FetchAPITask.shared.fetchAPI(url: url)
self.datas = datas
}
} catch {
print(error)
}
}
Task.init(priority: .default, operation: {
await self.fetchAllAPI()
DispatchQueue.main.async {
self.mainTableView.reloadData()
}
})
Kết luận
- Sử dụng async await với syntax đơn giản hơn dễ đọc hơn giúp việc đọc hiểu và maintain sẽ dễ dàng hơn
- Các vấn đề với closure (điển hình như việc nhiều callback lồng nhau)
- Đây là một ví dụ về việc sử dụng async await call api async await còn rất nhiều thứ hay ho mọi người có thể đọc tại đây