检查来自 Alamofire 和 Swift 的多个异步响应 [英] Checking for multiple asynchronous responses from Alamofire and Swift

查看:20
本文介绍了检查来自 Alamofire 和 Swift 的多个异步响应的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写一个依赖于来自不同站点/服务的数据的应用程序,并涉及基于来自这些不同来源的数据执行计算以生成最终产品.

I am writing an application that depends on data from various sites/service, and involves performing calculations based on data from these different sources to produce an end product.

我编写了一个示例类,其中包含以下两个函数,用于从两个来源收集数据.我选择让函数与众不同,因为有时我们会根据来源应用不同的身份验证方法,但在本示例中,我只是将它们简化为最简单的形式.这两个函数都使用 Alamofire 来触发和处理请求.

I have written an example class with two functions below that gathers data from the two sources. I have chosen to make the functions different, because sometimes we apply different authentication methods depending on the source, but in this example I have just stripped them down to their simplest form. Both of the functions use Alamofire to fire off and handle the requests.

然后我有一个初始化函数,它表示如果我们成功地从两个来源收集了数据,则加载另一个 nib 文件,否则等待几秒钟,如果没有返回响应,则加载服务器错误 nib 文件.

I then have an initialisation function, which says if we have successfully gathered data from both sources, then load another nib file, otherwise wait up to for seconds, if no response has been returned, then load a server error nib file.

我试图使这个例子尽可能简单.本质上.这是我想遵循的逻辑.不幸的是,这在当前的实现中似乎不起作用.

I've tried to make this example as simple as possible. Essentially. This is the kind of logic I would like to follow. Unfortunately it appears this does not currently work in its current implementation.

import Foundation

class GrabData{
    var data_source_1:String?
    var data_source_2:String?

    init(){    
        // get data from source 1
        get_data_1{ data_source_1 in
            println("(data_source_1)")
        }

        // get data from source 2
        get_data_2{ data_source_1 in
            println("(data_source_1)")
        }

        var timer = 0;
        while(timer<5){
            if((data_source_1 == nil) && (data_source_2 == nil)){
                // do nothing unless 4 seconds has elapsed
                if (timer == 4){
                    // load server error nib
                }
            }else{
                // load another nib, and start manipulating data
            }
            // sleep for 1 second
            sleep(1)
            timer = timer+1
        }    
    }

    func get_data_1(completionHandler: (String) -> ()) -> () {
        if let datasource1 = self.data_source_1{
            completionHandler(datasource1)
        }else{
            var url = "http://somewebsite.com"
            Manager.sharedInstance.request(.GET, url).responseString {
                (request, response, returnedstring, error) in
                println("getting data from source 1")
                let datasource1 = returnedstring
                self.data_source_1 = datasource1
                completionHandler(datasource1!)
            }
        }
    }

    func get_data_2(completionHandler: (String) -> ()) -> () {    
        if let datasource2 = self.data_source_2{
            completionHandler(datasource2)
        }else{
            var url = "http://anotherwebsite.com"
            Manager.sharedInstance.request(.GET, url).responseString {
                (request, response, returnedstring, error) in
                println("getting data from source 2")
                let datasource2 = returnedstring
                self.data_source_2 = datasource2
                completionHandler(datasource2!)
            }
        }
    }
}

我知道我可以将第二个闭包放在 init 函数内的第一个闭包中,但是,我认为这不是最佳实践,而且我实际上从两个以上的来源中提取,因此闭包将是 n 个闭包很深.

I know that i could put the second closure within the first inside the init function, however, I don't think this would be best practice and I am actually pulling from more than 2 sources, so the closure would be n closures deep.

任何有助于找出检查多个数据源是否提供有效响应的最佳方法并适当处理的帮助将不胜感激.

Any help to figuring out the best way to checking if multiple data sources gave a valid response, and handling that appropriately would be much appreciated.

推荐答案

比循环过程会阻塞线程更好,您可以使用调度组来跟踪请求何时完成.因此,在发出每个请求之前进入"该组,在请求完成后离开"该组,并设置一个通知"块/闭包,该块将在该组的所有任务完成时调用.

Better than that looping process, which would block the thread, you could use dispatch group to keep track of when the requests were done. So "enter" the group before issuing each of the requests, "leave" the group when the request is done, and set up a "notify" block/closure that will be called when all of the group's tasks are done.

例如,在 Swift 3 中:

For example, in Swift 3:

let group = DispatchGroup()

group.enter()
retrieveDataFromURL(url1, parameters: firstParameters) {
    group.leave()
}

group.enter()
retrieveDataFromURL(url2, parameters: secondParameters) {
    group.leave()
}

group.notify(queue: .main) {
    print("both requests done")
}

或者,在 Swift 2 中:

Or, in Swift 2:

let group = dispatch_group_create()

dispatch_group_enter(group)
retrieveDataFromURL(url1, parameters: firstParameters) {
    dispatch_group_leave(group)
}

dispatch_group_enter(group)
retrieveDataFromURL(url2, parameters: secondParameters) {
    dispatch_group_leave(group)
}

dispatch_group_notify(group, dispatch_get_main_queue()) {
    print("both requests done")
}

另一种方法是将这些请求包装在一个异步 NSOperation 子类中(使它们可取消,让您可以控制并发程度等),但这更复杂,因此您可能想从上面显示的调度组开始.

The other approach is to wrap these requests within an asynchronous NSOperation subclass (making them cancelable, giving you control over constraining the degree of concurrency, etc.), but that's more complicated, so you might want to start with dispatch groups as shown above.

这篇关于检查来自 Alamofire 和 Swift 的多个异步响应的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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