正在异步获取 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()
    }      
}