如何在Swift中处理异步请求? [英] How do I handle async requests in Swift?

查看:83
本文介绍了如何在Swift中处理异步请求?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在其中一项功能中进行了Web服务调用。我在构造它时遇到了麻烦,因此逻辑是干净的并且不是多余的。这是我的财产:

I make a web service call in one of my functions. I'm having trouble how to structure it so the logic is clean and not redundant. Here's what I have:

public func getTimes() -> [TimeName: MyResult] {
    let deferredTask: () -> [TimeName: MyResult] = {
        var computed = self.computeTimes()
        // Do something
        return computed
    }

    // Calculate timezone
    if let tz = timezone {
        timeZone = tz
        return deferredTask()
    } else {
        NSURLSession.sharedSession().dataTaskWithURL(NSURL(string: url)!) {
            (data, response, error) in

            // Do something with data

            return deferredTask() // Getting a compiler error here btw: is not convertible to 'Void'
        }.resume()
    }
}

然后我用 MyInstance.getTimes()来称呼它。某件事感觉不对..设置 deferredTask 变量是避免冗余代码的好方法吗?

Then I call this using MyInstance.getTimes(). Something doesn't feel right though.. is setting up a deferredTask variable a good way to avoid redundant code?

此外,当我从另一个函数调用此函数时,将使用 var test = MyInstance.getTimes()。但这意味着 test 处于异步状态,在Web服务在 getTimes

Also, when I call this from another function, I would use var test = MyInstance.getTimes(). But this means test is in an async state and I can't use it in my other function until the web service is finished in getTimes.

在Swift中处理此问题的好方法是什么?

What's a good way to handle this in Swift?

推荐答案

正如您正确地说的那样,您不能这样做:

As you rightly say, you cannot do this:

public func getTimes() -> [TimeName: MyResult] {
    let deferredTask: () -> [TimeName: MyResult] = {
        var computed = self.computeTimes()
        // Do something
        return computed
    }
    NSURLSession.sharedSession().dataTaskWithURL(NSURL(string: url)!) {
            (data, response, error) in
            // Do something with data
            return deferredTask()
     }.resume()
}

问题,正如我认为您正确地说的那样,是 return deferredTask()从周围的闭包中返回-而不是从 getTimes 中返回。您不能从函数调用中异步返回值!这就是异步的本质。

The problem, as I think you are correctly trying to say, is that return deferredTask() is returned from the surrounding closure - not from getTimes. You cannot asynchronously return a value from a function call! That is the nature of asynchrony.

典型的标准解决方案是编写 getTimes 本身以接受回调函数,例如它的参数。它本身不返回任何内容。异步方法完成后,它将调用回调,从而在将来的某个时间将信息返回给原始调用者。

A typical standard solution is to write getTimes itself to accept a callback function as its parameter. It itself returns nothing. When the asynchronous method is finished, it calls the callback, thus getting the info back, at some future time, to the original caller.

为了向您展示我的意思,我将完全从故事中删除您的 deferredTask ,而只专注于异步任务和回调。因此,我们将得到:

To show you what I mean, I'm going to remove your deferredTask entirely from the story and just concentrate on the asynchronous task and the callback. So we would have this:

public func getTimes(f:(Any) -> Void) -> () {
    NSURLSession.sharedSession().dataTaskWithURL(NSURL(string: url)!) {
            (data, response, error) in
            // ...
            f(whatever)
     }.resume()
}

此体系结构的要点是对 f(whatever)的呼叫实际上可以追溯到谁首先将我们交给 f 的人-特别是如果该实体将自己放在某个地方。

The point of this architecture is that the call to f(whatever) effectively goes back to whoever handed us f in the first place - especially if that entity put self into it somewhere.

这篇关于如何在Swift中处理异步请求?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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