如何一个一个地发出多个网络请求,这样我就不会丢失数据?

How to make multiple network requests one by one so I don't lose data?

我有以下场景 - 我有一个应用程序需要在后台从服务器异步获取一些音频文件。音频文件很大——比如 10000。它们是 1-2 秒的 mp3 文件(每个 5-10 kb)。对于这些文件中的每一个,我都必须发出网络请求并使用其 ID 获取文件。有两种类型的音频文件 - 用于您的母语和您的学习语言。所以我像这样检查所有 ID - 1. 获取 ID 为 1 的原生音频,然后获取 ID 为 1 的学习音频 ---> ID+1 并再次出现相同的场景。

问题是当我这样做时,一些音频文件最后损坏了。我想这是因为我没有正确执行异步请求。这是我的代码:

DispatchQueue.global(qos: .background).async {
let myGroup = DispatchGroup()

for category in arrCategories {
    for library in category.libraries {
        for group in library.groups {
            for word in group.words {

                myGroup.enter()

                User.current.getAudioFile(forWord: word, language: User.current.nativeLanguage, isNative: true, callback: { (success) in
                    if success {
                        User.current.getAudioFile(forWord: word, language: User.current.learningLanguage, isNative: false, callback: { (success) in
                            if success {
                                myGroup.leave()
                            } else {
                                print("ERROR LEARNING")
                                myGroup.leave()
                            }
                        })
                    } else {
                        print("ERROR NATIVE")
                        myGroup.leave()
                    }
                })
            }
        }
    }
}

myGroup.notify(queue: DispatchQueue.main, execute: {
    print("READY")
    running = false
})

我的网络请求:

        request(urlRequest).response { (response) in

            if response.data != nil && response.error == nil {
                let soundData = response.data! as NSData
                let fileURL = URL(fileURLWithPath: filePath)

                do {
                    try soundData.write(to: fileURL, options: .atomic)
                    callback(true)
                } catch {
                    print(error)
                    callback(false)
                }
            } else {
                print(response.error?.localizedDescription)
                callback(false)
            }

有人能告诉我代码有什么问题吗?因为如果我使用这种方法,有些音频文件不会播放。但是,如果我只下载这个文件而不进行这么多请求,它可以正常播放。

使用循环只是启动所有异步请求。您的问题在于处理所有并行响应。

一个选择是在完成第一个循环之前使用 mutex/semaphor 来阻止循环(我不建议这样做。

第二个选项是创建一个请求列表,当一个请求完成时开始下一个。

绝对是一份 OperationQueue and BlockOperation 的工作。使用 BlockOperation,您甚至可以将一个依赖项添加到另一个依赖项,并确保所有项都已执行。

这是一个想法(未经测试的代码):

var queue = OperationQueue()
var previousOp: BlockOperation ? = nil
for task in tasks {
    let op = BlockOperation { your code }
    if previousOp != nil {
        previousOp.addDepencendy(op)
    }
    previousOp = op
}