PromiseKit与OMGHTTPURLRQ:请求超时的异步处理
【免费下载链接】PromiseKit Promises for Swift & ObjC. 项目地址: https://gitcode.com/gh_mirrors/pr/PromiseKit
你是否在开发中遇到过网络请求超时导致的界面卡顿?是否为异步操作的错误处理感到头疼?本文将带你了解如何使用PromiseKit结合OMGHTTPURLRQ优雅地解决请求超时问题,让你的应用网络请求更稳定、用户体验更流畅。读完本文,你将掌握PromiseKit的超时处理机制、OMGHTTPURLRQ的基本使用以及两者结合的实战技巧。
PromiseKit的超时处理基础
PromiseKit提供了after函数来创建延迟执行的异步操作,这是实现超时处理的基础。其核心原理是通过race函数让网络请求和超时定时器竞速,谁先完成就执行对应的处理逻辑。
after函数的实现
after函数的源码位于Sources/after.swift,它接受一个时间间隔参数,返回一个在指定时间后完成的Guarantee对象:
public func after(seconds: TimeInterval) -> Guarantee<Void> {
let (rg, seal) = Guarantee<Void>.pending()
let when = DispatchTime.now() + seconds
q.asyncAfter(deadline: when) { seal(()) }
return rg
}
基本超时模式
在Documentation/CommonPatterns.md中介绍了使用race实现超时的标准模式:
let fetches: [Promise<T>] = makeFetches()
let timeout = after(seconds: 4)
race(when(fulfilled: fetches).asVoid(), timeout).then {
// 请求成功处理
}.catch { error in
// 超时或其他错误处理
}
OMGHTTPURLRQ的请求封装
OMGHTTPURLRQ是一个轻量级的HTTP请求库,PromiseKit对其进行了扩展,使其支持Promise风格的异步调用。虽然我们无法直接获取到扩展文件,但可以推测其实现类似于其他网络库的Promise封装。
典型的请求封装方式
参照PromiseKit对其他网络库的扩展(如Alamofire),OMGHTTPURLRQ的Promise封装可能如下:
extension OMGHTTPURLRQ {
static func dataTask(with request: URLRequest) -> Promise<Data> {
return Promise { seal in
let task = self.dataTask(with: request) { data, response, error in
if let error = error {
seal.reject(error)
} else if let data = data {
seal.fulfill(data)
} else {
seal.reject(PMKError.emptyData)
}
}
task.resume()
}
}
}
结合使用PromiseKit与OMGHTTPURLRQ处理超时
将PromiseKit的超时机制与OMGHTTPURLRQ的请求封装结合,可以构建出健壮的网络请求组件,确保在请求超时时能够及时响应并处理。
带超时的请求实现
func requestWithTimeout(url: URL, timeout: TimeInterval) -> Promise<Data> {
// 创建网络请求Promise
let requestPromise = OMGHTTPURLRQ.dataTask(with: URLRequest(url: url))
// 创建超时Promise
let timeoutPromise = after(seconds: timeout)
.then { Promise<Data> { seal in
seal.reject(PMKError.timedOut)
}
// 竞速选择先完成的Promise
return race(requestPromise, timeoutPromise)
}
完整的使用示例
firstly {
requestWithTimeout(url: apiURL, timeout: 5)
}.then { data in
// 处理返回数据
return processResponse(data: data)
}.done { result in
// 更新UI显示结果
updateUI(with: result)
}.catch { error in
if error == PMKError.timedOut {
showTimeoutAlert()
} else {
showError(message: error.localizedDescription)
}
}.ensure {
// 隐藏加载指示器
hideLoadingIndicator()
}
超时处理流程图
高级超时策略
除了基本的超时处理外,还可以根据实际需求实现更复杂的超时策略,提升应用的健壮性和用户体验。
指数退避重试
结合Documentation/CommonPatterns.md中的重试模式,可以实现请求超时后的指数退避重试:
func attemptRequest(with url: URL, maxRetries: Int = 3) -> Promise<Data> {
var attempts = 0
func attempt() -> Promise<Data> {
attempts += 1
let timeout = after(seconds: 5 * pow(2, Double(attempts - 1)))
return race(OMGHTTPURLRQ.dataTask(with: URLRequest(url: url)), timeout)
.recover { error -> Promise<Data> in
guard attempts < maxRetries, error == PMKError.timedOut else { throw error }
return after(seconds: pow(2, Double(attempts - 1))).then(attempt)
}
}
return attempt()
}
并发请求超时控制
使用when函数可以同时处理多个请求的超时控制,确保所有请求都在指定时间内完成:
func fetchMultipleResources() -> Promise<[Data]> {
let urls = [url1, url2, url3]
let requests = urls.map { url in
race(OMGHTTPURLRQ.dataTask(with: URLRequest(url: url)), after(seconds: 3))
}
return when(fulfilled: requests)
}
实战应用与最佳实践
在实际项目中,建议将超时处理逻辑封装为通用的网络请求工具类,统一管理超时时间、错误处理和重试策略,提高代码的可维护性和一致性。
统一的网络请求工具
class NetworkClient {
static let shared = NetworkClient()
private let timeout: TimeInterval = 10
func request(_ url: URL) -> Promise<Data> {
let request = OMGHTTPURLRQ.POST(url, json: ["key": "value"])
return race(
OMGHTTPURLRQ.dataTask(with: request),
after(seconds: timeout).then { throw NetworkError.timeout }
)
}
}
enum NetworkError: Error {
case timeout
case invalidResponse
// 其他错误类型
}
超时时间的合理设置
根据不同的网络环境和请求类型设置合适的超时时间:
- 普通API请求:3-5秒
- 大数据上传/下载:15-30秒
- 弱网络环境:适当延长超时时间
错误处理与用户反馈
超时错误应该被明确地反馈给用户,并提供重试选项,参考Documentation/CommonPatterns.md中的错误处理建议:
.catch { error in
if case NetworkError.timeout = error {
showErrorView(message: "请求超时,请检查网络后重试", retryAction: { [weak self] in
self?.fetchData()
})
}
}
通过PromiseKit与OMGHTTPURLRQ的结合使用,我们可以轻松实现网络请求的超时处理,避免应用因网络问题而无响应。合理运用race、after等函数,结合重试机制和用户反馈,可以显著提升应用的稳定性和用户体验。建议你在项目中引入这种异步超时处理模式,并根据实际需求调整超时时间和重试策略,让你的应用网络请求更加健壮可靠。
【免费下载链接】PromiseKit Promises for Swift & ObjC. 项目地址: https://gitcode.com/gh_mirrors/pr/PromiseKit
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



