简体   繁体   English

带循环的Alamofire同步请求

[英]Alamofire synchronous request with a loop

I know how to make a synchronous request with completions. 我知道如何与完成请求同步。 But I don't know how to make synchronous requests in a loop. 但是我不知道如何在循环中发出同步请求。

Here is my code: 这是我的代码:

    var marks = [JSON]()
    let vnCount = studentVnCodes.count

    var i: Int = 0

    marks = [JSON](repeating: JSON.null, count: vnCount)

    for vn in studentVnCodes {
        let url = "https://example.com/Student/Grade/GetFinalGrades?&vn=\(vn)&academic_year=All"

        Alamofire.request(url).responseString { response in

            var dataString: String = (response.result.value)!

            dataString = cleanMarksJSON(string: dataString)

            if let dict = convertToDictionary(text: dataString) {

                marks[i] = (JSON(dict as Any))

                i += 1

                if (vnCount == marks.count) {
                    completionHandler(marks)
                }
            }

        }
    }

Here I'm trying to make x requests with the number of vn codes ( vnCount ). 在这里,我尝试使用vn代码( vnCount )的数量发出x个请求。 The issue is that I get all the JSON in a wrong order in my array of JSON marks . 问题是我在JSON marks数组中以错误的顺序获取了所有JSON。 Certainly because it appends responses in the array when it's finished and don't wait the previous request to be ended. 当然是因为它在完成时将响应添加到数组中,而不必等待先前的请求结束。

So I tried to create a variable i to force the function to append responses in the right order. 因此,我尝试创建一个变量i来强制该函数以正确的顺序附加响应。 That's not working. 那不行 Any idea? 任何想法? Thanks! 谢谢!

You can run your requests sequentially in a serial queue, in which case they will be executed in the order you call them, which ensures they will be added to the array in order. 您可以在串行队列中顺序运行请求,在这种情况下,它们将按照调用它们的顺序执行,以确保将它们按顺序添加到数组中。 However, this seems like a suboptimal solution, since you lose execution time by running your requests sequentially instead of concurrently. 但是,这似乎是次优的解决方案,因为您通过顺序而不是同时运行请求来浪费执行时间。

If you still want to implement it like this, see the code below: 如果仍要像这样实现它,请参见下面的代码:

var marks = [JSON]()
let vnCount = studentVnCodes.count
marks = [JSON](repeating: JSON.null, count: vnCount)
let serialQueue = DispatchQueue(label: "serialQueue")
for vn in studentVnCodes {
    serialQueue.async{
        let url = "https://example.com/Student/Grade/GetFinalGrades?&vn=\(vn)&academic_year=All"
        Alamofire.request(url).responseString { response in
            var dataString: String = (response.result.value)!
            dataString = cleanMarksJSON(string: dataString)
            if let dict = convertToDictionary(text: dataString) {
                marks.append(JSON(dict as Any))
                if (vnCount == marks.count) {
                    completionHandler(marks)
                }
            }
        }
    }
}

A better solution would be to store the response in a data structure, where ordering doesn't matter, for example in a dictionary, where your keys are the indexes (which you would use for an array) and your values are the JSON response values. 更好的解决方案是将响应存储在数据结构中,其中顺序无关紧要,例如在字典中,其中键是索引(将用于数组),值是JSON响应值。 This way you can run the requests concurrently and access the responses in order. 这样,您可以同时运行请求并按顺序访问响应。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM