Open kemchenj opened 7 years ago
请教一个问题:
“这里偷懒没有转成 MoyaError
再抛出”
这里统一的error格式对于后续的错误处理有什么好的帮助吗,或者说服务端定义的业务error(就是这两个
var statusCode: Int
var message: String)也转换成MoyaError吗?
这里需要扩展MoyaError以支持statusCode和message吗?
或者说使用MoyaError的.underlying包装自己的error吗?
对这块一直没有什么明确的思路啊(T_T)
@ZHocean123 你可以想象一下写网络层的人不是你,你只负责搭建 UI 和调用网络层的 API,那网络层只有一种 Error 类型需要你处理会不会好一点?统一的 Error 类型对于调用方来说是一个很重要的约定,约定只要处理这一种 Error 就可以了。对于我来说,理想状态下,每个模块应该都抽象一个自己的 Error 类型出来。
服务端定义的业务 error,MoyaError
满足不了这个需求也不应该满足这个需求,如果你觉得有必要的话,可以定义一个自己的 NetworkError
,把服务端的业务 error 和 MoyaError 都包含进去,理论上说这么说会让代码更加健壮,例如说你想把 Moya 换了或者 MoyaError
改了,你也只需要处理 MoyaError
转换到 NetworkError
的这个过程就行了,而不需要去处理每一个 ViewController 里的 MoyaError
。
至于说文章里的那一句这里偷懒没有转成 MoyaError 再抛出
,是因为 MoyaError
已经在这个 Pull Request 里加上了 objectMapping
这个枚举值来表示解析错误的情况了,所以我才说应该要转成 MoyaError 再抛出。本来我是有稍微提一下这个 PR 的,但发表的时候觉得跟我要说的内容无关,最后就删了。
看了好多文章 博主写的好多都是我也琢磨过的- -, 这个里面有关注么 难道只能mark一下
@shanyanhai RSS 订阅或者 Twitter 关注我都可以
每一次解析都创建一个JSONDecoder对象会不会开销太大,可以写成类属性吗?
@Ginxx 我的答案是,不会,最好不要,这里看似有很大的优化的空间,但实际上并没有,理由有两个:
第一: JSONDecoder 内部保存着一个状态机,解析的函数并不是线程安全的,如果只用一个实例的话,多线程访问可能会产生错误。
如果要求达到线程安全,并且只使用一个 Decoder,那在并发的情况下会有点糟糕,因为同一时间你只能进行一个 decode 行为。为了避免这样的状况,去构建一个 Decoder 的重用池,那整体的复杂度就上去了,并且重用机制也会带来性能消耗,你确定会比直接创建一个 JSONDecoder 消耗更低吗?
而如果你并发的情况并不多,那 JSONDecoder 还会是你的性能瓶颈吗?
第二: 移动端跟服务端不同,JSON 解析绝对是一个低频次的操作,我现在工作的公司是做股票的,一个页面多个接口 3 秒一次轮询, JSONDecoder 的创建开销也远远算不上是瓶颈
我个人的看法是,不到必要的时候,不要去做优化,写好逻辑,构建好一个清晰的抽象会更加重要
@kemchenj 感谢大佬回答,纠结这个好久了。
@Pircate 我这两天翻了一下源码,发现我之前的理解有个很低级的错误😨,JSONDecoder
这个类只保存了一些 decodingStrategy,然后在 decode
方法被调用时,使用这些解析策略去生成 _JSONDecoder
的实例,所以 decode
是一个无副作用的方法,不会存在线程问题
open func decode<T : Decodable>(_ type: T.Type, from data: Data) throws -> T {
let topLevel: Any
do {
topLevel = try JSONSerialization.jsonObject(with: data)
} catch {
throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: [], debugDescription: "The given data was not valid JSON.", underlyingError: error))
}
let decoder = _JSONDecoder(referencing: topLevel, options: self.options)
guard let value = try decoder.unbox(topLevel, as: type) else {
throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: [], debugDescription: "The given data did not contain a top-level value."))
}
return value
}
@kemchenj 这个我也去看源码了,但是结论还是一样的对吧,没必要去创建一个JSONDecoder单例。
atom.xml ,feed,rss 这些关键字都试过了 ,没有找到博主的RSS订阅源..
@LockLight 加上了
@kemchenj 反应神速,谢谢
请问下 能提供一个 完整的demo吗?
https://kemchenj.github.io/2017-10-13/