接口请求的本地缓存策略

# 接口请求的本地缓存策略前端

 

本文是在 AFNetworking 的基础上,加入了本地缓存策略,并对请求错误,进行了定制,以统一前端对用户的错误提示。缓存

 

## 缓存策略服务器

 

包含3种策略,详见如下缓存策略的定义说明。网络

 

```优化

/**url

 接口缓存策略.net

 */orm

typedef NS_ENUM(NSUInteger, TTVRequestCachePolicy) {接口

    //一、先查询本地缓存ip

    //2.一、有缓存则直接返回

    //2.二、无缓存则请求服务器后返回,并更新本地缓存

    TTVRequestCachePolicyNormal,

    

    //不使用缓存,直接请求服务器

    TTVRequestCachePolicyOnline,

    

    //一、先查询本地缓存。

    //2.一、有缓存则返回,而后请求服务器再次返回,并更新本地缓存。

    //2.二、无缓存则联网请求服务器返回最新数据,并更新本地缓存。

    TTVRequestCachePolicyHybrid,

};

```

 

### 策略对应的业务需求

 

##### TTVRequestCachePolicyNormal

只取本地缓存的数据返回。同时在后台请求最新的数据,并更新缓存。

 

对应的业务需求是,一些更新周期很是长的数据,能够使用此种策略。

 

##### TTVRequestCachePolicyOnline

只请求最新的网络数据。

 

对应一些不须要使用到本地缓存的业务需求。

 

##### TTVRequestCachePolicyHybrid

先返回本地缓存数据,再返回最新的网络数据。

 

由于App端有一种通用的需求,就是在没有网络或网络较差时,须要先展现本地缓存的数据,同时请求最新数据,请求成功后,将获取到的最新数据更新到UI上。

 

 

 

## 请求成功或失败的回调block

 

### 请求成功的处理

 

```

/**

 请求的成功回调

 

 @param responseObject  返回的正确数据

 @param isCache         是否缓存

 */

typedef void (^TTVRequestSuccessBlock)(id  _Nullable responseObject, BOOL isCache);

```

 

指定的返回的数据,以及 `isCache` 表明是否来自本地缓存

 

### 请求失败的处理

 

```

/**

 请求的失败回调

 

 @param errCode     错误码

 @param errMessage  错误消息

 */

typedef void (^TTVRequestFailureBlock)(NSInteger errCode, NSString *_Nullable errMessage);

```

 

请求失败的回调block,指定了错误码和错误提示语,在调用请求接口时,可直接使用并展现给用户。

 

在请求过程当中,加入了网络错误的判断,直接返回指定的网络错误提示语,并中断请求。

 

 

## 有待优化

 

对于本地缓存策略,须要加入缓存有效期。

 

 

## 完整代码示例

 

```

/**

 GET或者POST请求

 

 @param isGetOrPost             YES:GET请求,NO:POST请求

 @param URLString               请求的URL

 @param parameters              请求参数

 @param cachePolicy             缓存策略

 @param cacheKey                缓存key,命名方式:模块名+id+userId

 @param downloadProgressBlock   请求成功下载加载进度回调Block

 @param successBlock            请求成功调用Block,Block中的responseObject参数

 @param failureBlock            请求失败调用Block

 @return

 */

+ (nonnull NSURLSessionDataTask *)request:(BOOL)isGetOrPost

                                      url:(nonnull NSString *)URLString

                               parameters:(nullable id)parameters

                              cachePolicy:(TTVRequestCachePolicy)cachePolicy

                                 cacheKey:(NSString *_Nullable)cacheKey

                                 progress:(void (^ _Nullable)(NSProgress * _Nonnull progress))downloadProgressBlock

                                  success:(TTVRequestSuccessBlock)successBlock

                                  failure:(TTVRequestFailureBlock)failureBlock

{

    TTVLogVerbose(@"GET Request with Cache>>>>>>>>>> [%@][%@]", URLString, parameters);

    AFHTTPSessionManager *manager = [TTVNetworkManager ttv_addHeaderForSignWithRequestURL:URLString mathod:isGetOrPost ? @"GET" : @"POST" parameters:parameters needToDecrypt:YES];

    

    __block YYCache *yyCache = [YYCache cacheWithName:@"TTVRequestCache"];

    

    //缓存key,加上版本号,用于升级接口后的数据更新

    __block NSString *cacheKeyFinal = [NSString stringWithFormat:@"%@+%@", cacheKey, [[self class] getServerAPIVesion:URLString]];

    

    //成功回调处理

    void (^doSuccessBlock)(id, BOOL) = ^(id responseObject, BOOL isCache) {

        

        TTVLogVerbose(@"GET Request with Cache Success<<<<<<<<<<[ %@ ]\n isCache:%@\n responseObject: %@ \n\n", URLString, @(isCache), responseObject);

        

        if (successBlock) {

            successBlock(responseObject, isCache);

            if (!isCache) {

                [self checkResponseObject:responseObject];

            }

        }

    };

    

    //失败回调处理

    void (^doFailureBlock)(NSError *, TTVRequestFailureBlock) = ^(NSError *error, TTVRequestFailureBlock failureBlock) {

        

        TTVLogWarn(@"GET Request with Cache Failure<<<<<<<<<<[ %@ ]\n%@\n\n", URLString, error);

        

        //返回具体的错误提示

        if (failureBlock) {

            TTVNetWorkError *netWorkError = [TTVNetWorkError ttv_errorWithError:error userInfo:error.userInfo];

            NSInteger errorCode = 0;

            if (error) {

                errorCode = [error.userInfo[@"body"][@"errorCode"] integerValue];

            }

            failureBlock(errorCode, netWorkError.ttv_tips);

        }

    };

    

    //请求

    void (^requestBlock)(BOOL) = ^(BOOL isGetOrPost)

    {

        /********************************

         无网络时,直接返回错误消息

         */

        AFNetworkReachabilityStatus status = [AFNetworkReachabilityManager sharedManager].networkReachabilityStatus;

        if (status == AFNetworkReachabilityStatusNotReachable) {

            if (failureBlock) {

                failureBlock(TTVRequestErrorCodeNoNetwork, TTVErrorMessageNoNetwork);

            }

            return;

        }

        

        /********************************

         网络正常时,继续请求

         */

        if (isGetOrPost) {

            [manager GET:URLString

              parameters:parameters

                progress:nil

                 success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject)

             {

                 doSuccessBlock(responseObject, NO);

                 [yyCache setObject:responseObject forKey:cacheKeyFinal];

             }

                 failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error)

             {

                 doFailureBlock(error, failureBlock);

             }];

        } else {

            [manager POST:URLString

               parameters:parameters

                 progress:nil

                  success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject)

             {

                 doSuccessBlock(responseObject, NO);

                 [yyCache setObject:responseObject forKey:cacheKeyFinal];

             }

                  failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error)

             {

                 doFailureBlock(error, failureBlock);

             }];

        }

    };

    

    /********************************

     处理数据,缓存逻辑

     */

    if (cachePolicy == TTVRequestCachePolicyNormal) {

        id cacheData = [yyCache objectForKey:cacheKeyFinal];

        if (cacheData) {

            //返回缓存

            doSuccessBlock(cacheData, YES);

        } else {

            //请求服务器

            requestBlock(isGetOrPost);

        }

    } else if (cachePolicy == TTVRequestCachePolicyOnline) {

        //请求服务器

        requestBlock(isGetOrPost);

    } else if (cachePolicy == TTVRequestCachePolicyHybrid) {

        //返回缓存

        id cacheData = [yyCache objectForKey:cacheKeyFinal];

        if (cacheData) {

            doSuccessBlock(cacheData, YES);

        }

        

        //请求服务器,再返回一次

        requestBlock(isGetOrPost);

    }

    

    //返回空

    return nil;

}

```

相关文章
相关标签/搜索