接口請求的本地緩存策略

# 接口請求的本地緩存策略前端

 

本文是在 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;

}

```

相關文章
相關標籤/搜索