博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
提供统一的错误API
阅读量:6175 次
发布时间:2019-06-21

本文共 3391 字,大约阅读时间需要 11 分钟。

我想分享一种技术,在使用Swift do, try, catch error处理模型时,我发现它非常有用,可以限制从给定API调用中抛出的错误数量。

目前,Swift不提供类型错误(在其他语言中称为“已检查的异常”,如Java),这意味着抛出的任何函数都可能抛出任何错误。虽然这为我们提供了很大的灵活性,但在使用API​​时,对于生产代码和测试来说,这也是一个挑战。

考虑以下函数,该函数通过从URL同步加载数据来执行操作:

class AClass {    enum SearchError: Error {        case invalidParameters(String)    }        func loadData(_ parameters: String) throws -> Data {        let urlString = "https://host/q=\(parameters)"                guard let url = URL(string: urlString) else {            throw SearchError.invalidParameters(parameters)        }                return try Data(contentsOf: url)}复制代码

正如您在上面所看到的,我们的函数可以结束在两个不同的位置(尝试构造URL时和使用URL 初始化Data时)。所以,这就是问题所在; 作为一个API用户,我很不清楚我可以期待这个函数抛出什么样的错误。我不需要知道这个函数在Data内部使用哪些类型,但我还需要知道Data初始化程序可以抛出哪些错误。

在API设计中,必须了解imlpementation细节通常是一个不好的迹象,所以如果我们能保证我们的函数只抛出SearchError类型的错误,那不是更好吗?幸运的是,它很容易修复。我们所要做的就是将对数据的调用包装在一个do, try, catch块中。重构以后的代码,像这样:

class AClass {    enum SearchError: Error {        case invalidParameters(String)        case loadingFailed(URL)    }        func loadData(_ parameters: String) throws -> Data {        let urlString = "https://host/q=\(parameters)"                guard let url = URL(string: urlString) else {            throw SearchError.invalidParameters(parameters)        }                do {            return try Data(contentsOf: url)        } catch {            throw SearchError.loadingFailed(url)        }    }}复制代码

我们上面所做的是将初始化Data抛出的异常替换为我们自己的错误。现在,我们可以记录我们的函数总是抛出一个SearchError,并且我们的API在错误处理方面变得更容易使用。

###然而,在使我们的API变得更好的同时,我们的实现也变得混乱了。通常,您需要使用do, try, catch块包装多个调用,这将使我们的代码很快变得难以阅读。为了解决这个问题,我创建了一个简单的函数来执行此包装,并在抛出基础错误时抛出特定错误。它看起来像这样:

func perform
(_ expression: @autoclosure () throws -> T, orThrow error: Error) throws -> T { do { return try expression() } catch let error { throw error }}复制代码

###使用它,我们现在可以从新更新我们的loadData功能,使其更简单:

func loadData(_ parameters: String) throws -> Data {        let urlString = "https://host/q=\(parameters)"                guard let url = URL(string: urlString) else {            throw SearchError.invalidParameters(parameters)        }                return try perform(Data(contentsOf: url), orThrow: SearchError.loadingFailed(url))    }复制代码

我们现在有一个统一的错误API和一个更简单的实现!

这种处理问题的思路,在Alamofire中也有体现,如JSONEncoding中的encode函数

public func encode(_ urlRequest: URLRequestConvertible, with parameters: Parameters?) throws -> URLRequest {        var urlRequest = try urlRequest.asURLRequest()        guard let parameters = parameters else { return urlRequest }        do {            let data = try JSONSerialization.data(withJSONObject: parameters, options: options)            if urlRequest.value(forHTTPHeaderField: "Content-Type") == nil {                urlRequest.setValue("application/json", forHTTPHeaderField: "Content-Type")            }            urlRequest.httpBody = data        } catch {            throw AFError.parameterEncodingFailed(reason: .jsonEncodingFailed(error: error))        }        return urlRequest    }复制代码

DataRequest中Requestable也有所体现:

func task(session: URLSession, adapter: RequestAdapter?, queue: DispatchQueue) throws -> URLSessionTask {            do {                let urlRequest = try self.urlRequest.adapt(using: adapter)                return queue.sync { session.dataTask(with: urlRequest) }            } catch {                throw AdaptError(error: error)            }        }复制代码

如果您有任何问题,建议或反馈,请随时与我联系~

转载地址:http://fahba.baihongyu.com/

你可能感兴趣的文章
站立会议02
查看>>
Windows和Linux如何使用Java代码实现关闭进程
查看>>
0428继承性 const static
查看>>
第一课:从一个简单的平方根运算学习平方根---【重温数学】
查看>>
NET反射系统
查看>>
Oracle12C本地用户的创建和登录
查看>>
使用JS制作一个鼠标可拖的DIV(一)——鼠标拖动
查看>>
HDU problem 5635 LCP Array【思维】
查看>>
leetcode10. 正则表达式匹配
查看>>
redis常用命令--zsets
查看>>
springcloud--Feign(WebService客户端)
查看>>
网络攻击
查看>>
sorting, two pointers(cf div.3 1113)
查看>>
Scala并发编程【消息机制】
查看>>
win10下安装Oracle 11g 32位客户端遇到INS-13001环境不满足最低要求
查看>>
AngularJS-01.AngularJS,Module,Controller,scope
查看>>
【MySQL 安装过程1】顺利安装MySQL完整过程
查看>>
Inno Setup入门(二十)——Inno Setup类参考(6)
查看>>
图片自适应
查看>>
amd cmd
查看>>