AlamoFire无响应:基于Vapor后端的简单爬虫开发异常
问题:Vapor后端中Alamofire请求回调无响应
我正尝试基于服务端Vapor后端,使用Alamofire开发一个简单的爬虫。Alamofire似乎已正常初始化,但回调处理器未产生任何响应。相关代码如下:
import Routing import Vapor import Alamofire public func routes(_ router: Router) throws { router.get("scrape") { req -> String in let stuff = Stuff(id: nil, sourcecode: "This saves to the database.") stuff.save(on: req) let q = Alamofire.request("http://sigh-fi.com/test.txt").responseString { response in // 这里的回调完全没触发 print(response) if let data = response.result.value { stuff.sourcecode = data stuff.save(on: req) } } return "Started scraping..." } }
解决方案
这个问题核心是Vapor路由闭包的同步特性和Alamofire异步请求的冲突,再加上线程调度的细节问题,下面一步步帮你解决:
1. 用EventLoopFuture处理异步逻辑
Vapor的路由闭包默认是同步执行的,你的代码里闭包会在Alamofire请求完成前就返回Started scraping...,后续回调操作也脱离了Vapor的异步上下文。你需要把路由返回类型改成EventLoopFuture<String>,用EventLoopPromise来包装Alamofire的异步结果:
public func routes(_ router: Router) throws { router.get("scrape") { req -> EventLoopFuture<String> in // 创建Promise管理异步结果 let promise = req.eventLoop.makePromise(of: String.self) let stuff = Stuff(id: nil, sourcecode: "This saves to the database.") // 先等待初始数据库保存完成,再发起请求 stuff.save(on: req).whenComplete { saveResult in switch saveResult { case .success: Alamofire.request("http://sigh-fi.com/test.txt").responseString { response in switch response.result { case .success(let data): stuff.sourcecode = data // 保存更新后的数据,同样等待操作完成 stuff.save(on: req).whenComplete { updateResult in if updateResult.isSuccess { promise.succeed("Scraping completed and saved!") } else { promise.fail(updateResult.error ?? Abort(.internalServerError)) } } case .failure(let error): promise.fail(error) } } case .failure(let error): promise.fail(error) } } // 返回Promise关联的Future return promise.futureResult } }
2. 把回调切换到Vapor的EventLoop
Alamofire的默认回调线程可能不在Vapor的EventLoop上,直接在回调里操作数据库可能引发线程安全问题。可以把回调逻辑调度回当前请求的EventLoop:
Alamofire.request("http://sigh-fi.com/test.txt").responseString { response in // 切换到Vapor的EventLoop执行后续操作 req.eventLoop.execute { // 这里处理response和数据库操作 } }
3. 添加错误调试排查问题
先在回调里打印错误信息,确认请求本身是否成功:
Alamofire.request("http://sigh-fi.com/test.txt").responseString { response in print("Response received: \(response)") if let error = response.result.error { print("Request error: \(error)") } // ... 其他逻辑 }
这样能快速排查是请求失败,还是回调未执行的问题。
内容的提问来源于stack exchange,提问作者Eric_WVGG
相关产品推荐
相关产品推荐

