《Effective 2.0》这本书中第 39 条:用 handler 块降低代码分散程度,建议“使用同一个块来处理成功与失败情况”,在实习的阶段刚好遇到这个情况,所以浅显的论述一下自己的观点,希望能有个抛砖引玉的效果。
API 如下:
EOCNetworkFetcher *fetcher = [[EOCNetworkFetcher alloc] initWithURL:url];
[fetcher startWithCompletionHander:^(NSData *data) {
// Handler success
}
failureHandler:^(NSError *error) {
// Handler failure
}];
优点:
API 如下:
EOCNetworkFetcher *fetcher = [[EOCNetworkFetcher alloc] initWithURL:url];
[fetcher startWithCompletionHander:^(NSData *data, NSError *error) {
if (error) {
// Handle failure
} else {
// Handle success
}
}];
优点:
根据自己的具体使用经验来分析我为什么推荐前者:
先给出我司在网络请求回调的处理方式(大概如下):
^(DQKDataModel *dataModel, DQKErrorModel *errorModel, NSError *error) {
// Handle …
}
Response 的 JSON 数据大概如下:
{
data = {
topic = “天气不错”;
};
respcd = “00”;
respmsg = “数据获取成功”;
}
回调的代码块就是上面的样子,分别是成功返回数据信息(data)、业务逻辑信息(respcd ,respmsg)、网络请求错误信息。一个代码块,数据可以统一处理。 我们一般不会去在 GET POST 中,获得很大的数据的 Response ,所以作者提到的这种数据一半就没了的情况基本是不会有的,我们从业务处理和网络处理两个情况来分析。
这里业务逻辑信息是指如登录密码错误,没有权限发帖等逻辑。
从网络请求层面分析,如果网络有问题,或者服务器处理出现错误等等,这个时候可能会出现错误 404 ,500 之类的情况,此时就不会有 JSON 数据的返回,那也就不会有返回数据信息,业务逻辑信息,因为这两个是同时在 JSON 中一起返回的。网络回调的层次应该如下所示:
成功返回数据信息 | 业务逻辑信息 |
网络请求错误信息 |
二者并没有什么可联系的关系,有数据一般就没有网络错误信息,没有数据一般就没有网络错误信息。
两个块的时候,一个块专注处理成功情况,一个块专注网络错误,不需要再去判断有那个数据,没有那个数据,会处理成功的代码块就一定是有数据的,会处理错误信息的代码就一定是网络请求中出现了某些问题。
同时这里还减少了一层鞭尸金字塔,更方便代码的维护和 Review 。
这里说的鞭尸金字塔就是类似这样的代码:
if (condition) {
if (condition) {
if (condition) {
if (condition) {
statements
} else if (expression) {
statements
} else {
statements
}
}
} else if (expression) {
statements
} else {
statements
}
} else {
statements
}
那么我们该怎么解决这种既需要处理网络请求错误,也需要处理业务逻辑错误呢?
我的方法如下:
^(DQKDataModel *dataModel) {
if (dataModel.error) {
// Handler data error
} else if (dataModel.data) {
// Handler data
}
} failureHandler:^(NSError *error) {
// Handler failure
}
对返回的数据处理生成两个属性,一个是业务错误信息,一个是数据成功信息,相比之前的处理可能会清晰一点。
如果您对网络请求的封装的有更好的想法、理解,欢迎大家一起讨论。 补充(2015-8-24):和 @画渣程序猿mmoaay (opens new window) 简单讨论了下,可以考虑这样的处理,在封装处理中把 self(UIViewController) 传进去,然后错误处理(以及停止下拉刷新等操作)就可以都封装在里面处理,外部 API 只留一个成功返回的块。