首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >方法在从Combine Future Publisher接收数据之前结束

方法在从Combine Future Publisher接收数据之前结束
EN

Stack Overflow用户
提问于 2020-03-09 21:31:54
回答 1查看 259关注 0票数 0

我有这样的代码:

代码语言:javascript
代码运行次数:0
运行
复制
import Cocoa
import Combine

func prepareURLRequest(for url: URL) -> URLRequest {
    let request = URLRequest(url: url)
    var token = "token"

    print("start value: \(token)")

    let subscription = Token()
    subscription.getToken()
        .sink(receiveCompletion: { _ in
        print("subscription completed")
    }, receiveValue: { value in
        token = value
        print("value received: \(token)")
    })

    print("new value: \(token)")

    // attach received token to request
    return request
}


class Token {
    let token = PassthroughSubject<String,Never>()

    func verify() -> Bool {
        // TODO: Token verification logic
        Bool.random()
    }

    func getToken() -> AnyPublisher<String,Never> {
        return Future<String, Never> { promise in
            if self.verify() {
                let url = URLRequest(url: URL(string: "http://avatars.io/twitter/twostraws")!)
                URLSession.shared.dataTask(with: url) { data, response, error in
                    print("Data Task started")
                    if let error = error {
                        print("error \(error)")

                    }
                    guard let data = data else {
                        preconditionFailure("data error")
                    }
                    guard let response = response as? HTTPURLResponse else {
                        preconditionFailure("response error")
                    }

                    print("data task received response with code: \(response.statusCode)")
                    promise(.success("\(response.statusCode)"))
                }.resume()
            } else {
                print("keychain path")
                sleep(2)
                promise(.success("kwychain path success"))
            }
        }.eraseToAnyPublisher()
    }
}

let url = URL(string: "http://avatars.io/twitter/twostraws")!
let request = prepareURLRequest(for: url)

代码应将接收的令牌附加到准备好的请求对象。现在,唯一的verify -> false path以所需的顺序返回数据。当我尝试在prepareURLRequest结束其生命周期后,verify -> true路径数据被接收。

如何修复这一问题,使两个路径都有正确的顺序(并且在prepareURLRequest方法结束之前更新令牌?

EN

回答 1

Stack Overflow用户

发布于 2020-03-13 09:03:47

你遇到的问题是,你没有用一个延迟来包装未来。您编写的代码期望在请求请求之前不会进行API调用,但这并不完全是Future的工作方式。

一旦创建了Future,它就会调用它的底层异步API调用来呈现-而你使用的是上面的PassthroughSubject,这意味着当你有一个订阅者请求数据时,它已经被调用了。解决此问题的最好方法是将Future包装在Deferred发布服务器中,该发布服务器等待创建它,直到订阅请求数据为止。

这里有an example of wrapping Future with Deferred in the Future reference page of Using Combine,以及更多关于未来如何工作以及其他运营商如何使用它的信息。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60601645

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档