与DispatchGroup同步的Alamofire请求 [英] Synchronous Alamofire Request with DispatchGroup

查看:217
本文介绍了与DispatchGroup同步的Alamofire请求的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要等到Alamofire请求完成数据获取. (错误或值).我在另一个函数的for循环内调用Alamofire函数,以便Alamofire请求应在调用第二个for循环之前完成.例如;第一个循环->第一个请求->第二个循环->第二个请求...等等.现在,它进入第一个循环->第二个循环->并且在所有循环完成后,请求响应正在转向.

I need to wait until Alamofire request finishes getting data. (Error or value). I'm calling Alamofire function inside a for loop in another function so that Alamofire requests should be finished before second for loop called. For example; first loop -> first request -> second loop -> second request...so on. Now It goes first loop -> second loop -> and after all loops finishes requests response is turning.

请求功能:

 func like(sender_id: String, completion: @escaping (String?) -> ()){
    let group = DispatchGroup()
    if let key = api_key{
        let headers: HTTPHeaders = [
            "X-Auth-Token": key,
            "Accept": "application/json"
        ]
        group.enter()
        Alamofire.request(baseUrl + likeURL + sender_id, method: .get, parameters: nil, encoding: URLEncoding.default, headers: headers).validate()
            .responseJSON { (response) -> Void in
                guard response.result.isSuccess else {
                    print("Error while doing : \(response.result.error)")
                    completion(nil)
                    group.leave()
                    return
                }
                if let error = response.error{
                    completion(nil)
                    group.leave()
                    print("Error Occured with Request: \(error)")
                }
                if let jsonData = response.data{
                    let json = JSON(data: jsonData)
                    print(json)
                    group.leave()
                    if let matched = json["match"].bool{
                        completion(matched.description)
                        print("Liked!: \(matched)")
                        if(matched){
                        }
                    }else{
                        group.leave()
                        "There is an error with JSON"
                    }
                }}
    }
}

我在哪里打电话:

 func like_all(completion: @escaping() -> ()){
    for user in SharedUsers.sharedUser.users{
        if let id = user.id{
            Network.sharedInstance.like(sender_id: id) { result in
                print(result)
            }
        }
        else{
            continue
        }
    }
    completion()
}

推荐答案

您正在使用调度组,显然是为了在函数末尾等待该组.但是您没有等待它,因此您没有得到想要的同步行为.

You are using dispatch group, obviously with the intent on waiting for the group at the end of the function. But you're not waiting for it, so you're not getting the synchronous behavior you were looking for.

但这很好,因为如果您在主线程上对该组(或信号灯,用于实现此行为的其他模式)进行wait设置,则不仅会阻塞主线程(这将导致可怕的用户体验和风险)让您的应用被看门狗进程杀死),因为responseJSON使用主队列作为完成处理程序,您将陷入僵局.因此,在对调度组/信号量添加wait()调用之前,请确保将整个for循环异步调度到某个后台线程.这样可以避免阻塞主线程,并消除了死锁的风险.

But that's good, because if you wait for that group (or semaphore, the other pattern to achieve this behavior) on the main thread, not only will you be blocking the main thread (which results in horrible UX and risk having your app killed by watchdog process), you're going to deadlock because responseJSON uses the main queue for it's completion handler. So before you add the wait() call on your dispatch group/semaphore, make sure you dispatch this whole for loop asynchronously to some background thread. That avoids blocking the main thread and eliminates the deadlock risk.

但是整个模式从根本上来说是有缺陷的,因为您真的不应该使用调度组或信号量使其完全同步.这引发了一些问题:

But this whole pattern is fundamentally flawed, as you really shouldn't use dispatch groups or semaphores to make it synchronous at all. That raises a few questions:

第一个问题是为什么要使其同步.网络请求具有固有的延迟,因此您执行一系列请求将非常慢.仅在绝对必要时才执行此请求序列(例如,无法形成每个请求,因为它需要来自先前请求的响应中的某些内容).但这似乎并非如此.那么为什么要使此过程变得不必要呢?

The first question is why you want to make this synchronous. Network requests have inherent latency, so you performing a sequence of them will be very slow. Only do this sequence of requests if you absolutely have to (e.g. each request cannot be formed because it needs something from the response of the prior request). But that doesn't appear to be the case here. So why make this process unnecessary so.

但是让我们假设您绝对必须顺序执行这些操作(据我所知,这里不是真的,但是让我们来梳理一下).然后,有两种模式可以连续而不是同时执行一系列请求:

But let's assume for a second that you absolutely have to perform these sequentially (not true here, from what I can tell, but let's tease this out). Then there are two patterns for performing a series of requests consecutively rather than concurrently:

  • 您可以完全丢失此for循环,而只需在其完成处理程序中使用一个例程即可发送第n个请求并发送请求n + 1.完全不需要调度组/信号量来阻塞线程.

  • You can either lose this for loop entirely, and simply have a routine that sends the n-th request and sends request n+1 in its completion handler. That completely eliminates the need for dispatch groups/semaphores to block a thread.

或者您可以将其包装在操作中(例如 https://stackoverflow.com/a/27022598/1271826)并使用操作队列.

Or you can wrap this in operation (e.g. https://stackoverflow.com/a/27022598/1271826) and use operation queue.

这篇关于与DispatchGroup同步的Alamofire请求的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆