正在异步获取 API 数据并每 1 秒调用一次
Fetching API data asynchronously and making calls every 1 second
我有一个功能:
func fetchHistoricalCurrencyData(completion: @escaping (() -> ())) {
let g = DispatchGroup()
DispatchQueue.main.async { [weak self] in
var historicalCurrencyDataTemp = [HistoricalCurrencyDataModel]()
let dayDurationInSeconds: TimeInterval = 60*60*24
for date in stride(from: self!.startingDate, to: self!.endingDate, by: dayDurationInSeconds) {
g.enter()
APIManager.shared.getHistoricalCurrencyData(date: self!.convertDateToStringDate(date: date), fromCurrency: String(self!.fromCurrency.prefix(3)), amount: self!.amount, toCurrency: String(self!.toCurrency.prefix(3))) {
historicalCurrencyDataModel in
historicalCurrencyDataTemp.append(historicalCurrencyDataModel)
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
g.leave()
}
}
}
g.notify(queue:.main) {
self?.historicalCurrencyData = DataManager.shared.getHistoricalCurrencyData(historicalCurrencyDataModels: historicalCurrencyDataTemp)
print(self?.historicalCurrencyData)
completion()
}
}
}
此外,我有一个 dateRange,我使用 stride()
函数将其划分为该范围内的特定日期。每天我都从这个函数中得到,我用它来进行 API 调用以获取所需的数据。我得到的每个 API 数据都被转换为特定的 HistoricalCurrencyDataModel
并附加到我在循环之前创建的临时数组 (historicalCurrencyDataTemp
)。当我收到我想要的所有数据时,我使用 DataManager
class 将这些数据转换为 [String: Double]
字典,我最终将其分配给我的 @Published var historicalCurrencyData: [String: Double]
变量。
一个线索是 API 我使用它可以使 API 至少在 1 秒后一个接一个地调用,所以我必须在每次调用之间创建 1 秒的延迟。我用 DispatchQueue.main.asyncAfter(deadline: .now() + 1)
语句使它成为可能。我用 DispatchGroup()
控制整个异步操作流程。
不幸的是,在所有这些之后,我在 print(self?.historicalCurrencyData)
语句中得到的是空 Optional([:])
。例如,正确的行为是,如果我在 5 天内使用 dateRange,我会得到一个包含 5 个条目的字典。
我最终摆脱了所有 DispatchQueues
,现在它可以正常工作了。我相信延迟有问题,并不是所有的值都被正确获取。更重要的是,我发现在阅读 API 文档后我认为在 API 调用之间不需要创建 1 秒。我一定是错了。
按照建议(我同意)附上工作代码:
func fetchHistoricalCurrencyData(completion: @escaping (() -> ())) {
let g = DispatchGroup()
var historicalCurrencyDataTemp = [HistoricalCurrencyDataModel]()
for date in stride(from: self.startingDate, to: self.endingDate, by: dayDurationInSeconds) {
g.enter()
APIManager.shared.getHistoricalCurrencyData(date: self.convertDateToStringDate(date: date), fromCurrency: String(self.fromCurrency.prefix(3)), amount: self.amount, toCurrency: String(self.toCurrency.prefix(3))) {
historicalCurrencyDataModel in
historicalCurrencyDataTemp.append(historicalCurrencyDataModel)
g.leave()
}
}
g.notify(queue:.main) {
self.historicalCurrencyData = DataManager.shared.getHistoricalCurrencyData(historicalCurrencyDataModels: historicalCurrencyDataTemp)
print(self.historicalCurrencyData)
completion()
}
}
我有一个功能:
func fetchHistoricalCurrencyData(completion: @escaping (() -> ())) {
let g = DispatchGroup()
DispatchQueue.main.async { [weak self] in
var historicalCurrencyDataTemp = [HistoricalCurrencyDataModel]()
let dayDurationInSeconds: TimeInterval = 60*60*24
for date in stride(from: self!.startingDate, to: self!.endingDate, by: dayDurationInSeconds) {
g.enter()
APIManager.shared.getHistoricalCurrencyData(date: self!.convertDateToStringDate(date: date), fromCurrency: String(self!.fromCurrency.prefix(3)), amount: self!.amount, toCurrency: String(self!.toCurrency.prefix(3))) {
historicalCurrencyDataModel in
historicalCurrencyDataTemp.append(historicalCurrencyDataModel)
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
g.leave()
}
}
}
g.notify(queue:.main) {
self?.historicalCurrencyData = DataManager.shared.getHistoricalCurrencyData(historicalCurrencyDataModels: historicalCurrencyDataTemp)
print(self?.historicalCurrencyData)
completion()
}
}
}
此外,我有一个 dateRange,我使用 stride()
函数将其划分为该范围内的特定日期。每天我都从这个函数中得到,我用它来进行 API 调用以获取所需的数据。我得到的每个 API 数据都被转换为特定的 HistoricalCurrencyDataModel
并附加到我在循环之前创建的临时数组 (historicalCurrencyDataTemp
)。当我收到我想要的所有数据时,我使用 DataManager
class 将这些数据转换为 [String: Double]
字典,我最终将其分配给我的 @Published var historicalCurrencyData: [String: Double]
变量。
一个线索是 API 我使用它可以使 API 至少在 1 秒后一个接一个地调用,所以我必须在每次调用之间创建 1 秒的延迟。我用 DispatchQueue.main.asyncAfter(deadline: .now() + 1)
语句使它成为可能。我用 DispatchGroup()
控制整个异步操作流程。
不幸的是,在所有这些之后,我在 print(self?.historicalCurrencyData)
语句中得到的是空 Optional([:])
。例如,正确的行为是,如果我在 5 天内使用 dateRange,我会得到一个包含 5 个条目的字典。
我最终摆脱了所有 DispatchQueues
,现在它可以正常工作了。我相信延迟有问题,并不是所有的值都被正确获取。更重要的是,我发现在阅读 API 文档后我认为在 API 调用之间不需要创建 1 秒。我一定是错了。
按照建议(我同意)附上工作代码:
func fetchHistoricalCurrencyData(completion: @escaping (() -> ())) {
let g = DispatchGroup()
var historicalCurrencyDataTemp = [HistoricalCurrencyDataModel]()
for date in stride(from: self.startingDate, to: self.endingDate, by: dayDurationInSeconds) {
g.enter()
APIManager.shared.getHistoricalCurrencyData(date: self.convertDateToStringDate(date: date), fromCurrency: String(self.fromCurrency.prefix(3)), amount: self.amount, toCurrency: String(self.toCurrency.prefix(3))) {
historicalCurrencyDataModel in
historicalCurrencyDataTemp.append(historicalCurrencyDataModel)
g.leave()
}
}
g.notify(queue:.main) {
self.historicalCurrencyData = DataManager.shared.getHistoricalCurrencyData(historicalCurrencyDataModels: historicalCurrencyDataTemp)
print(self.historicalCurrencyData)
completion()
}
}