Swift3 如何使用swift 3进行同步url请求
我知道以前有人问过这个问题,我同意大多数的回答,他们认为最好遵循Swift 3中与URLSession异步的请求方式。我有以下场景,其中不能使用异步请求 有了Swift 3和在服务器上运行Swift的能力,我有以下问题Swift3 如何使用swift 3进行同步url请求,swift3,alamofire,vapor,kitura,Swift3,Alamofire,Vapor,Kitura,我知道以前有人问过这个问题,我同意大多数的回答,他们认为最好遵循Swift 3中与URLSession异步的请求方式。我有以下场景,其中不能使用异步请求 有了Swift 3和在服务器上运行Swift的能力,我有以下问题 服务器接收来自客户端的请求 要处理请求,服务器必须发送url请求并等待响应到达 一旦收到响应,处理它并回复给客户机 问题出现在第2步,其中URLSession使我们能够仅启动异步数据任务。大多数(如果不是全部的话)服务器端swift web框架不支持异步响应。当一个请求到达服务器
extension URLSession {
func synchronousDataTaskWithURL(_ url: URL) -> (Data?, URLResponse?, Error?) {
var data: Data?
var response: URLResponse?
var error: Error?
let sem = DispatchSemaphore(value: 0)
let task = self.dataTask(with: url as URL, completionHandler: {
data = $0
response = $1
error = $2 as Error?
sem.signal()
})
task.resume()
let result = sem.wait(timeout: DispatchTime.distantFuture)
switch result {
case .success:
return (data, response, error)
case .timedOut:
let error = URLSessionError(kind: URLSessionError.ErrorKind.timeout)
return (data, response, error)
}
}
}
我只有使用kitura web框架的经验,这就是我面临的问题所在。我认为所有其他swift web框架中都存在类似的问题。在Vapor中,您可以使用Droplet的客户端来进行同步请求
let res = try drop.client.get("https://httpbin.org")
print(res)
此外,您可以使用门户
类使异步任务同步
let res = try Portal.open { portal in
asyncClient.get("https://httpbin.org") { res in
portal.close(with: res)
}
}
您的三步问题可以通过使用完成处理程序来解决,即回调处理程序和la Node.js约定:
import Foundation
import Kitura
import HeliumLogger
import LoggerAPI
let session = URLSession(configuration: URLSessionConfiguration.default)
Log.logger = HeliumLogger()
let router = Router()
router.get("/test") { req, res, next in
let datatask = session.dataTask(with: URL(string: "http://www.example.com")!) { data, urlResponse, error in
try! res.send(data: data!).end()
}
datatask.resume()
}
Kitura.addHTTPServer(onPort: 3000, with: router)
Kitura.run()
这是您的问题解决方案的快速演示,绝不遵循最佳Swift/Kitura实践。但是,通过使用完成处理程序,我可以让我的Kitura应用程序在http://www.example.com
,等待响应,然后将结果发送回我的应用程序的客户端
链接到相关API:从未想过这个简单的解决方案。我的印象是,您应该在同一线程中使用“res”,而不是在完成块中使用。当你说“非最佳实践”时,你能解释一下原因吗?@zirinisp I没有包括正确的错误处理或可选的展开(
如果let data=data
)。对于来自dataTask
的错误和来自res.send
的可能错误(可能会重新引用第二个错误),您应该在生产代码中包含错误处理。我认为“非最佳实践”是从块发送响应。只要这不是一个问题,那么这就是解决方案(我的头脑被卡住了,正在寻找复杂的替代方案)。非常感谢。看来Vapor已经看透了。我更喜欢第二种方法,因为它对任何场景都是通用的(不绑定到特定的框架)