JKNetworking 升级之JKBatchRequest优化升级

Posted JackLee18

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JKNetworking 升级之JKBatchRequest优化升级相关的知识,希望对你有一定的参考价值。

  之前写了关于网络请求框架的文章《网络请求框架需求梳理》,《打造一款高稳定易扩展的网络请求框架JKNetworking》,最近结合实际的业务,对JKBatchRequest进行了升级。

目的

  将单个网络请求的成功回调,失败回调与JKBatchRequest的成功回调,失败回调进行分离。单个网络请求的成功回调,失败回调用来处理数据的解析与装饰。JKBatchRequest的成功回调,失败回调用来作为UI刷新的时机。这样可以是网络请求这一块的逻辑更加的清晰,同时能够减少重复刷新的情况

实现

   我这次创建了JKBatchRequest和JKChainRequest的父类JKGroupRequest.
具体源码如下:

@interface JKGroupRequest : NSObject
/// the array of the JKBaseRequest
@property (nonatomic, strong, readonly) NSMutableArray<__kindof JKBaseRequest *> *requestArray;
/// the class to handle the request indicator
@property (nonatomic, strong, nullable) Class<JKRequestAccessoryProtocol> requestAccessory;

- (void)addRequest:(__kindof JKBaseRequest *)request;

- (void)addRequestsWithArray:(NSArray<__kindof JKBaseRequest *> *)requestArray;

- (void)start;

- (void)stop;
//非上传,下载网络请求加入batchRequest时需要配置相关的block,每个请求成功或者失败时执行配置的block
+ (void)configNormalRequest:(__kindof JKBaseRequest *)request
                    success:(void(^)(__kindof JKBaseRequest *request))successBlock
                    failure:(void(^)(__kindof JKBaseRequest *request))failureBlock;
//上传网络请求加入batchRequest时需要配置相关的block,每个请求成功或者失败时执行配置的block
+ (void)configUploadRequest:(__kindof JKBaseUploadRequest *)request
                   progress:(nullable void(^)(NSProgress *progress))uploadProgressBlock
              formDataBlock:(nullable void(^)(id <AFMultipartFormData> formData))formDataBlock
                    success:(nullable void(^)(__kindof JKBaseRequest *request))successBlock
                    failure:(nullable void(^)(__kindof JKBaseRequest *request))failureBlock;
//下载网络请求加入batchRequest时需要配置相关的block,每个请求成功或者失败时执行配置的block

+ (void)configDownloadRequest:(__kindof JKBaseDownloadRequest *)request
                     progress:(nullable void(^)(NSProgress *downloadProgress))downloadProgressBlock
                      success:(nullable void(^)(__kindof JKBaseRequest *request))successBlock
                      failure:(nullable void(^)(__kindof JKBaseRequest *request))failureBlock;

@end
@interface JKGroupRequest()

/// the array of the JKBaseRequest
@property (nonatomic, strong, readwrite) NSMutableArray<__kindof JKBaseRequest *> *requestArray;
/// the block of success
@property (nonatomic, copy, nullable) void (^successBlock)(__kindof JKGroupRequest *request);
/// the block of failure
@property (nonatomic, copy, nullable) void (^failureBlock)(__kindof JKGroupRequest *request);
/// the count of finished requests
@property (nonatomic, assign) NSInteger finishedCount;
/// the status of the JKGroupRequest is executing or not
@property (nonatomic, assign) BOOL executing;


@end

@implementation JKGroupRequest

- (instancetype)init

    self = [super init];
    if (self) 
        _requestArray = [NSMutableArray new];
        _finishedCount = 0;
    
    return self;


- (void)addRequest:(__kindof JKBaseRequest *)request

    if (![request isKindOfClass:[JKBaseRequest class]]) 
#if DEBUG
        NSAssert(NO, @"makesure [request isKindOfClass:[JKBaseRequest class]] be YES");
#endif
        return;
    
    if ([self.requestArray containsObject:request]) 
#if DEBUG
        NSAssert(NO, @"request was added");
#endif
        return;
    
    request.isIndependentRequest = NO;
    [self.requestArray addObject:request];


- (void)addRequestsWithArray:(NSArray<__kindof JKBaseRequest *> *)requestArray

    NSMutableSet *tmpSet = [NSMutableSet setWithArray:requestArray];
    if (tmpSet.count != requestArray.count) 
#if DEBUG
        NSAssert(NO, @"requestArray has duplicated requests");
#endif
        return;
    
    NSMutableSet *requestSet = [NSMutableSet setWithArray:self.requestArray];
    BOOL hasCommonRequest = [requestSet intersectsSet:tmpSet];
    if (hasCommonRequest) 
#if DEBUG
        NSAssert(NO, @"requestArray has common request with the added requests");
#endif
        return;
    
    for (JKBaseRequest *request in requestArray) 
        if (![request isKindOfClass:[JKBaseRequest class]]) 
#if DEBUG
            NSAssert(NO, @"makesure [request isKindOfClass:[JKBaseRequest class]] be YES");
#endif
            return;
        
        request.isIndependentRequest = NO;
    
    [self.requestArray addObjectsFromArray:requestArray];


- (void)start

    


- (void)stop

    


+ (void)configNormalRequest:(__kindof JKBaseRequest *)request
                    success:(void(^)(__kindof JKBaseRequest *request))successBlock
                    failure:(void(^)(__kindof JKBaseRequest *request))failureBlock;

    NSAssert(request.requestType == JKRequestTypeDefault, @"make sure request.requestType == JKRequestTypeDefault be YES");
    request.groupSuccessBlock = successBlock;
    request.groupFailureBlock = failureBlock;


+ (void)configUploadRequest:(__kindof JKBaseUploadRequest *)request
                   progress:(nullable void(^)(NSProgress *progress))uploadProgressBlock
              formDataBlock:(nullable void(^)(id <AFMultipartFormData> formData))formDataBlock
                    success:(nullable void(^)(__kindof JKBaseRequest *request))successBlock
                    failure:(nullable void(^)(__kindof JKBaseRequest *request))failureBlock

    NSAssert(request.requestType == JKRequestTypeUpload, @"make sure request.requestType == JKRequestTypeUpload be YES");
    request.progressBlock = uploadProgressBlock;
    request.formDataBlock = formDataBlock;
    request.groupSuccessBlock = successBlock;
    request.groupFailureBlock = failureBlock;


+ (void)configDownloadRequest:(__kindof JKBaseDownloadRequest *)request
                     progress:(nullable void(^)(NSProgress *downloadProgress))downloadProgressBlock
                      success:(nullable void(^)(__kindof JKBaseRequest *request))successBlock
                      failure:(nullable void(^)(__kindof JKBaseRequest *request))failureBlock

    NSAssert(request.requestType == JKRequestTypeDownload, @"make sure request.requestType == JKRequestTypeDownload be YES");
    request.progressBlock = downloadProgressBlock;
    request.groupSuccessBlock = successBlock;
    request.groupFailureBlock = failureBlock;


- (void)clearCompletionBlock

    if (self.successBlock) 
        self.successBlock = nil;
    
    if (self.failureBlock) 
        self.failureBlock = nil;
    


@end

下面是JKBatchRequest 的源码,具体如下


@interface JKBatchRequest : JKGroupRequest

/// the failed requests
@property (nonatomic, strong, readonly, nullable) NSMutableArray<__kindof JKBaseRequest *> *failedRequests;

/*
 config the require success requests
 if not config,or the config requests has no elment, only one request success, the batchRequest success block will be called;only all requests in batchRequest failed,the batchRequest fail block will be called.
 if config the requests,only the requests in the config requests all success,then the batchRequest success block will be called,if one of request in config request failed,the batchRequest fail block will be called.
 this method should invoke after you add the request in the batchRequest.
 */
- (void)configRequireSuccessRequests:(nullable NSArray <__kindof JKBaseRequest *> *)requests;

- (void)startWithCompletionSuccess:(nullable void (^)(JKBatchRequest *batchRequest))successBlock
                           failure:(nullable void (^)(JKBatchRequest *batchRequest))failureBlock;

@end
#pragma mark - - JKBatchRequest - -

@interface JKBatchRequest()

@property (nonatomic, strong, readwrite, nullable) NSMutableArray<__kindof JKBaseRequest *> *failedRequests;
@property (nonatomic, strong, nullable) NSMutableArray<__kindof JKBaseRequest *> *requireSuccessRequests;


@end

@implementation JKBatchRequest

- (void)start

    if (self.requestArray.count == 0) 
#if DEBUG
        NSAssert(NO, @"please makesure self.requestArray.count > 0");
#endif
        return;
    
    if (self.executing) 
        return;
    
    self.executing = YES;
    if (self.requestAccessory
        && [self.requestAccessory respondsToSelector:@selector(requestWillStart:)]) 
        [self.requestAccessory requestWillStart:self];
    
    for (__kindof JKBaseRequest *request in self.requestArray) 
        @weakify(self);
        [request startWithCompletionSuccess:^(__kindof JKBaseRequest * _Nonnull request) 
            @strongify(self);
            self.finishedCount++;
            if (request.groupSuccessBlock) 
                request.groupSuccessBlock(request);
            
            
            if (self.finishedCount == self.requestArray.count) 
                [self finishAllRequestsWithBlock];
            
         failure:^(__kindof JKBaseRequest * _Nonnull request) 
            @strongify(self);
            if (!self.failedRequests) 
                self.failedRequests = [NSMutableArray new];
            
            if ([self.requireSuccessRequests containsObject:request]) 
                [self.failedRequests addObject:request];
                if (request.groupFailureBlock) 
                    request.groupFailureBlock(request);
                
                for (__kindof JKBaseRequest *tmpRequest in [self.requestArray copy]) 
                    [tmpRequest stop];
                
                if (self.requestAccessory
                    && [self.requestAccessory respondsToSelector:@selector(requestWillStop:)]) 
                    [self.requestAccessory requestWillStop:self];
                
                if (self.failureBlock) 
                    self.failureBlock(self);
                
                if (self.requestAccessory
                    && [self.requestAccessory respondsToSelector:@selector(requestDidStop:)]) 
                    [self.requestAccessory requestDidStop:self];
                
                [self stop];
             else 
                self.finishedCount++;
                [self.failedRequests addObject:request];
                if (request.groupFailureBlock) 
                    request.groupFailureBlock(request);
                
                if (self.finishedCount == self.requestArray.count) 
                    [self finishAllRequestsWithBlock];
                
            
        ];
    


- (void)finishAllRequestsWithBlock

    if (self.failedRequests.count != self.requestArray.count) 
           if (self.requestAccessory
               && [self.requestAccessory respondsToSelector:@selector(requestWillStop:)]) 
               [self.requestAccessory requestWillStop:self];
           
           if (self.successBlock) 
               self.successBlock(self);
           
           if (self.requestAccessory
               && [self.requestAccessory respondsToSelector:@selector(requestDidStop:)]) 
               [self.requestAccessory requestDidStop:self];
           
           [self stop];
    else 
        if (self.requestAccessory
            && [self.requestAccessory respondsToSelector:@selector(requestWillStop:)]) 
            [self.requestAccessory requestWillStop:self];
        
        if (self.failureBlock) 
            self.failureBlock(self);
        
        if (self.requestAccessory
            && [self.requestAccessory respondsToSelector:@selector(requestDidStop:)]) 
            [self.requestAccessory requestDidStop:self];
        
        [self stop];
    


- (void)stop

    [self clearCompletionBlock];
    self.finishedCount = 0;
    self.failedRequests = nil;
    [[JKNetworkAgent sharedAgent] removeBatchRequest:self];
    self.executing = NO;


- (void)configRequireSuccessRequests:(nullable NSArray <__kindof JKBaseRequest *> *)requests


    for (__kindof JKBaseRequest *request in requests) 
        if (![request isKindOfClass:[JKBaseRequest class]]) 
#if DEBUG
            NSAssert(NO, @"please make sure [request isKindOfClass:[JKBaseRequest class]] be YES");
#endif
            return;
        
    
    self.requireSuccessRequests = [NSMutableArray arrayWithArray:requests];


- (void)startWithCompletionSuccess:(nullable void (^)(JKBatchRequest *batchRequest))successBlock
                           failure:(nullable void (^)(JKBatchRequest *batchRequest))failureBlock

    self.successBlock = successBlock;
    self.failureBlock = failureBlock;
    [[JKNetworkAgent sharedAgent] addBatchRequest:self];


@end

实现主要是按照下面这个思路:
组队列发送网络请求,一组网络请求,异步发送,可以指定某几个请求是必须成功的请求,只有指定的请求都成功时,才会执行组队列的成功回调;如果指定的任意一个请求失败,那么执行组队列的失败回调。如果没有指定必须成功的请求,那么只要有一个请求成功,那么等到所有的请求执行完,执行组队列的成功回调;如果所有的请求都失败了,那么执行组队列的失败回调。

单元测试

   由于网络请求需要处理的场景比较多,为了尽可能多的验证网络请求的场景, 我这边写了一些单测样例进行验证,其中https://123/mock/17这个链接进行了脱敏, 大家实际验证时需要换成能够请求成功的接口进行操作,具体如下:

#import <Kiwi/Kiwi.h>
#import <AFNetworking/AFNetworking.h>
#import "JKNetworking.h"

SPEC_BEGIN(JKRequestSpec)

describe(@"BaseRequest", ^
         beforeAll(^
 #if DEBUG
     AFSecurityPolicy *policy = [AFSecurityPolicy defaultPolicy];
     policy.validatesDomainName = NO;
     policy.allowInvalidCertificates = YES;
     [JKNetworkConfig sharedConfig].securityPolicy = policy;
 #endif
    [JKNetworkConfig sharedConfig].baseUrl = @"https://123/mock/17";
);
    
    context(@"single request", ^

        it(@"return success", ^
            JKBaseRequest *request = [JKBaseRequest new];
            request.requestUrl = @"/a1";
            request.requestSerializerType = JKRequestSerializerTypeHTTP;
            request.responseSerializerType = JKResponseSerializerTypeJSON;

            __block BOOL success = NO;
            [request startWithCompletionSuccess:^(__kindof JKBaseRequest * _Nonnull request) 
                success = YES;
             failure:^(__kindof JKBaseRequest * _Nonnull request) 

            ];
            [[expectFutureValue(theValue(success)) shouldAfterWaitOf(5)] beYes];
        );

        it(@"return failure", ^
            //失败的网络请求
            JKBaseRequest *request = [JKBaseRequest new];
            request.baseUrl = @"https://aacoioio.com";
            request.requestUrl = @"/aaa";
            request.requestSerializerType = JKRequestSerializerTypeHTTP;
            request.responseSerializerType = JKResponseSerializerTypeJSON;
            request.requestTimeoutInterval = 5;
            __block BOOL fail = NO;
            [request startWithCompletionSuccess:^(__kindof JKBaseRequest * _Nonnull request) 

             failure:^(__kindof JKBaseRequest * _Nonnull request) 
                fail = YES;
            ];
            [[expectFutureValue(theValue(fail)) shouldAfterWaitOf(6)] beYes];
        );

        it(@"use same request instance repeat start requests", ^
            JKBaseRequest *request = [JKBaseRequest new];
            request.requestUrl = @"/a1";
            request.requestSerializerType = JKRequestSerializerTypeHTTP;
            request.responseSerializerType = JKResponseSerializerTypeJSON;

            __block BOOL success = NO;
            [request startWithCompletionSuccess:^(__kindof JKBaseRequest * _Nonnull request) 
                success = YES;
                [[request.responseObject shouldNot] beNil];
                [[request.responseJSONObject shouldNot] beNil];
                [request startWithCompletionSuccess:nil failure:nil];
                [[request.responseObject should] beNil];
                [[request.responseJSONObject should] beNil];
             failure:^(__kindof JKBaseRequest * _Nonnull request) 

            ];
            [[expectFutureValue(theValue(success)) shouldAfterWaitOf(3)] beYes];
        );

        it(@"use cache", ^
            // 后续缓存升级后,进行单元测试
        );

    );

    context(@"batch request", ^
        beforeEach(^
            [[JKNetworkAgent sharedAgent] cancelAllRequests];
        );
        it(@"addRequest,request is not a JKBaseRequest", ^
            JKBatchRequest *batchRequest = [JKBatchRequest new];
            JKChainRequest *request = [JKChainRequest new];
            [[theBlock(^
                [batchRequest addRequest:request];
            ) should] raiseWithReason:@"makesure [request isKindOfClass:[JKBaseRequest class]] be YES"];
        );

        it(@"addRequest,request has added in", ^
            JKBatchRequest *batchRequest = [JKBatchRequest new];
            JKBaseRequest *request = [JKBaseRequest new];
            [batchRequest addRequest:request];
            [[batchRequest.requestArray should] haveCountOf:1];
            [[theBlock(^
                [batchRequest addRequest:request];
            ) should] raiseWithReason:@"request was added"];
        );

        it(@"addRequestsWithArray,array has repeated requests", ^
            JKBatchRequest *batchRequest = [JKBatchRequest new];
            JKBaseRequest *request = [JKBaseRequest new];
            NSArray *array = @[request,request];
            [[theBlock(^
                [batchRequest addRequestsWithArray:array];
            ) should] raiseWithReason:@"requestArray has duplicated requests"];
        );

        it(@"addRequestsWithArray,array has a request not a JKBaseRequest", ^
           JKBatchRequest *batchRequest = [JKBatchRequest new];
            JKBaseRequest *request = [JKBaseRequest new];
            JKChainRequest *chainRequest = [JKChainRequest new];
            NSArray *array = @[request,chainRequest];
            [[theBlock(^
                [batchRequest addRequestsWithArray:array];
            ) should] raiseWithReason:@"makesure [request isKindOfClass:[JKBaseRequest class]] be YES"];
        );

        it(@"addRequestsWithArray,array has a request add in", ^
            JKBatchRequest *batchRequest = [JKBatchRequest new];
            JKBaseRequest *request1 = [JKBaseRequest new];
            JKBaseRequest *request2 = [JKBaseRequest new];
            [batchRequest addRequest:request1];
            NSArray *array = @[request1,request2];
            [[theBlock(^
                [batchRequest addRequestsWithArray:array];
            ) should] raiseWithReason:@"requestArray has common request with the added requests"];
        );

        it(@"addRequestsWithArray,normal", ^
            JKBatchRequest *batchRequest = [JKBatchRequest new];
            JKBaseRequest *request1 = [JKBaseRequest new];
            JKBaseRequest *request2 = [JKBaseRequest new];
            NSArray *array = @[request1,request2];
            [batchRequest addRequestsWithArray:array];
            [[batchRequest.requestArray should] haveCountOf:2];
        );

        it(@"configRequireSuccessRequests,requests is equal requestArray,require all success,all request success", ^
            JKBatchRequest *batchRequest = [JKBatchRequest new];
            JKBaseRequest *request1 = [JKBaseRequest new];
            request1.requestUrl = @"/a1";
            request1.requestSerializerType = JKRequestSerializerTypeHTTP;
            request1.responseSerializerType = JKResponseSerializerTypeJSON;
            __block BOOL success1 = NO;
            [JKBatchRequest configNormalRequest:request1 success:^(__kindof JKBaseRequest * _Nonnull request) 
                success1 = YES;
                [[request should] equal:request1];
             failure:^(__kindof JKBaseRequest * _Nonnull request) 

            ];
            JKBaseRequest *request2 = [JKBaseRequest new];
            request2.requestUrl = @"/a2";
            request2.requestSerializerType = JKRequestSerializerTypeHTTP;
            request2.responseSerializerType = JKResponseSerializerTypeJSON;
            __block BOOL success2 = NO;
            [JKBatchRequest configNormalRequest:request2 success:^(__kindof JKBaseRequest * _Nonnull request) 
                success2 = YES;
                [[request should] equal:request2];
             failure:^(__kindof JKBaseRequest * _Nonnull request) 

            ];
            NSArray *array = @[request1,request2];
            [batchRequest addRequestsWithArray:array];
            [batchRequest configRequireSuccessRequests:array];
            __block BOOL success3 = NO;
            [batchRequest startWithCompletionSuccess:^(JKBatchRequest * _Nonnull batchRequest) 
                success3 = YES;
             failure:^(JKBatchRequest * _Nonnull batchRequest) 

            ];

            [[expectFutureValue(theValue(success1)) shouldAfterWaitOf(6)] beYes];
            [[expectFutureValue(theValue(success2)) shouldAfterWaitOf(6)] beYes];
            [[expectFutureValue(theValue(success3)) shouldAfterWaitOf(6)] beYes];

        );
        
        it(@"configRequireSuccessRequests,requests is only has request1,require request1 success,all request success", ^
            JKBatchRequest *batchRequest = [JKBatchRequest new];
            JKBaseRequest *request1 = [JKBaseRequest new];
            request1.requestUrl = @"/a1";
            request1.requestSerializerType = JKRequestSerializerTypeHTTP;
            request1.responseSerializerType = JKResponseSerializerTypeJSON;
            __block BOOL success1 = NO;
            [JKBatchRequest configNormalRequest:request1 success:^(__kindof JKBaseRequest * _Nonnull request) 
                success1 = YES;
                [[request should] equal:request1];
             failure:^(__kindof JKBaseRequest * _Nonnull request) 

            ];
            //失败的网络请求
            JKBaseRequest *request2 = [JKBaseRequest new];
            request2.baseUrl = @"https://aacoioio.com";
            request2.requestUrl = @"/aaa";
            request2.requestSerializerType = JKRequestSerializerTypeHTTP;
            request2.responseSerializerType = JKResponseSerializerTypeJSON;
            request2.requestTimeoutInterval = 3;
            __block BOOL fail1 = NO;
            [JKBatchRequest configNormalRequest:request2 success:^(__kindof JKBaseRequest * _Nonnull request) 
                
             failure:^(__kindof JKBaseRequest * _Nonnull request) 
                fail1 = YES;
                [[request should] equal:request2];

            ];
            NSArray *array = @[request1,request2];
            [batchRequest addRequestsWithArray:array];
            [batchRequest configRequireSuccessRequests:@[request1]];
            __block BOOL success3 = NO;
            __block BOOL fail2 = NO;

            [batchRequest startWithCompletionSuccess:^(JKBatchRequest * _Nonnull batchRequest) 
                success3 = YES;
             failure:^(JKBatchRequest * _Nonnull batchRequest) 
                fail2 = YES;
            ];

            [[expectFutureValue(theValue(success1)) shouldAfterWaitOf(6)] beYes];
            [[expectFutureValue(theValue(fail1)) shouldAfterWaitOf(6)] beYes];
            [[expectFutureValue(theValue(success3)) shouldAfterWaitOf(6)] beYes];
            

        );
        
        it(@"configRequireSuccessRequests,requests is equal requestArray,one request failed", ^
            JKBatchRequest *batchRequest = [JKBatchRequest new];
            JKBaseRequest *request1 = [JKBaseRequest new];
            request1.requestUrl = @"/a1";
            request1.requestSerializerType = JKRequestSerializerTypeHTTP;
            request1.responseSerializerType = JKResponseSerializerTypeJSON;
            [JKBatchRequest configNormalRequest:request1 success:^(__kindof JKBaseRequest * _Nonnull request) 

             failure:^(__kindof JKBaseRequest * _Nonnull request) 

            ];
            //失败的网络请求
            JKBaseRequest *request2 = [JKBaseRequest new];
            request2.baseUrl = @"https://aacoioio.com";
            request2.requestUrl = @"/aaa";
            request2.requestSerializerType = JKRequestSerializerTypeHTTP;
            request2.responseSerializerType = JKResponseSerializerTypeJSON;
            request2.requestTimeoutInterval = 3;
            __block BOOL fail1 = NO;
            [JKBatchRequest configNormalRequest:request2 success:^(__kindof JKBaseRequest * _Nonnull request) 

             failure:^(__kindof JKBaseRequest * _Nonnull request) 
                fail1 = YES;
                [[request should] equal:request2];

            ];

            JKBaseRequest *request3 = [JKBaseRequest new];
            request3.requestUrl = @"/a2";
            request3.requestMethod = JKRequestMethodPOST;
            request3.requestSerializerType = JKRequestSerializerTypeHTTP;
            request3.responseSerializerType = JKResponseSerializerTypeJSON;
            [JKBatchRequest configNormalRequest:request1 success:^(__kindof JKBaseRequest * _Nonnull request) 

             failure:^(__kindof JKBaseRequest * _Nonnull request) 

            ];

            NSArray *array = @[request1,request2,request3];
            [batchRequest addRequestsWithArray:array];
            [batchRequest configRequireSuccessRequests:array];
            __block BOOL fail2 = NO;
            [batchRequest startWithCompletionSuccess:^(JKBatchRequest * _Nonnull batchRequest) 

             failure:^(JKBatchRequest * _Nonnull batchRequest) 
                fail2 = YES;
                [[theValue([batchRequest.failedRequests containsObject:request2]) should] beYes];
            ];

            [[expectFutureValue(theValue(fail1)) shouldAfterWaitOf(5)] beYes];
            [[expectFutureValue(theValue(fail2)) shouldAfterWaitOf(5)] beYes];
        );

        it(@"configRequireSuccessRequests,requests is nil,one request success", ^
            JKBatchRequest *batchRequest = [JKBatchRequest new];
            JKBaseRequest *request1 = [JKBaseRequest new];
            request1.requestUrl = @"/a1";
            request1.requestSerializerType = JKRequestSerializerTypeHTTP;
            request1.responseSerializerType = JKResponseSerializerTypeJSON;
            [JKBatchRequest configNormalRequest:request1 success:^(__kindof JKBaseRequest * _Nonnull request) 

             failure:^(__kindof JKBaseRequest * _Nonnull request) 

            ];
            //失败的网络请求
            JKBaseRequest *request2 = [JKBaseRequest new];
            request2.baseUrl = @"https://aacoioio.com";
            request2.requestUrl = @"/aaa";
            request2.requestSerializerType = JKRequestSerializerTypeHTTP;
            request2.responseSerializerType = JKResponseSerializerTypeJSON;
            request2.requestTimeoutInterval = 3;
            __block BOOL fail1 = NO;
            [JKBatchRequest configNormalRequest:request2 success:^(__kindof JKBaseRequest * _Nonnull request) 

             failure:^(__kindof JKBaseRequest * _Nonnull request) 
                fail1 = YES;
                [[request should] equal:request2];

            ];
            //失败的网络请求
            JKBaseRequest *request3 = [JKBaseRequest new];
            request3.baseUrl = @"https://aacoioio.com";
            request3.requestUrl = @"/aaa1";
            request3.requestSerializerType = JKRequestSerializerTypeHTTP;
            request3.responseSerializerType = JKResponseSerializerTypeJSON;
            request3.requestTimeoutInterval = 3;
            __block BOOL fail2 = NO;
            [JKBatchRequest configNormalRequest:request3 success:^(__kindof JKBaseRequest * _Nonnull request) 

             failure:^(__kindof JKBaseRequest * _Nonnull request) 
                fail2 = YES;
                [[request should] equal:request3];

            ];

            NSArray *array = @[request1,request2,request3];
            [batchRequest addRequestsWithArray:array];
            __block BOOL success = NO;
            [batchRequest startWithCompletionSuccess:^(JKBatchRequest * _Nonnull batchRequest) 
                success = YES;
                [[expectFutureValue(theValue([batchRequest.failedRequests containsObject:request2])) shouldAfterWaitOf(5)] beYes];
                [[expectFutureValue(theValue([batchRequest.failedRequests containsObject:request3])) shouldAfterWaitOf(5)] beYes];
             failure:^(JKBatchRequest * _Nonnull batchRequest) 

            ];

            [[expectFutureValue(theValue(fail1)) shouldAfterWaitOf(5)] beYes];
            [[expectFutureValue(theValue(fail2)) shouldAfterWaitOf(5)] beYes];


        );

        it(@"configRequireSuccessRequests,requests is nil,all requests failed", ^
            //失败的网络请求
            JKBatchRequest *batchRequest = [JKBatchRequest new];
            JKBaseRequest *request1 = [JKBaseRequest new];
            request1.baseUrl = @"https://aacoioio.com";
            request1.requestUrl = @"/aaa1";
            request1.requestSerializerType = JKRequestSerializerTypeHTTP;
            request1.responseSerializerType = JKResponseSerializerTypeJSON;
            request1.requestTimeoutInterval = 3;
            __block BOOL fail1 = NO;
            [JKBatchRequest configNormalRequest:request1 success:^(__kindof JKBaseRequest * _Nonnull request) 

             failure:^(__kindof JKBaseRequest * _Nonnull request) 
                fail1 = YES;
                [[request should] equal:request1];

            ];
            //失败的网络请求
            JKBaseRequest *request2 = [JKBaseRequest new];
            request2.baseUrl = @"https://aacoioio.com";
            request2.requestUrl = @"/aaa2";
            request2.requestSerializerType = JKRequestSerializerTypeHTTP;
            request2.responseSerializerType = JKResponseSerializerTypeJSON;
            request2.requestTimeoutInterval = 3;
            __block BOOL fail2 = NO;
            [JKBatchRequest configNormalRequest:request2 success:^(__kindof JKBaseRequest * _Nonnull request) 

             failure:^(__kindof JKBaseRequest * _Nonnull request) 
                fail2 = YES;
                [[request should] equal:request2];

            ];
            //失败的网络请求
            JKBaseRequest *request3 = [JKBaseRequest new];
            request3.baseUrl = @"https://aacoioio.com";
            request3.requestUrl = @"/aaa3";
            request3.requestSerializerType = JKRequestSerializerTypeHTTP;
            request3.responseSerializerType = JKResponseSerializerTypeJSON;
            request3.requestTimeoutInterval = 3;
            __block BOOL fail3 = NO;
            [JKBatchRequest configNormalRequest:request3 success:^(__kindof JKBaseRequest * _Nonnull request) 

             failure:^(__kindof JKBaseRequest * _Nonnull request) 
                fail3 = YES;
                [[request should] equal:request3];

            ];

            NSArray *array = @[request1,request2,request3];
            [batchRequest addRequestsWithArray:array];
            __block BOOL fail4 = NO;
            [batchRequest startWithCompletionSuccess:^(JKBatchRequest * _Nonnull batchRequest) 

             failure:^(JKBatchRequest * _Nonnull batchRequest) 
                fail4 = YES;
                [[expectFutureValue(theValue([batchRequest.failedRequests containsObject:request1])) shouldAfterWaitOf(5)] beYes];
                [[expectFutureValue(theValue([batchRequest.failedRequests containsObject:request2])) shouldAfterWaitOf(5)] beYes];
                [[expectFutureValue(theValue([batchRequest.failedRequests containsObject:request3])) shouldAfterWaitOf(5)] beYes];
            ];

            [[expectFutureValue(theValue(fail1)) shouldAfterWaitOf(5)] beYes];
            [[expectFutureValue(theValue(fail2)) shouldAfterWaitOf(5)] beYes];
            [[expectFutureValue(theValue(fail3)) shouldAfterWaitOf(5)] beYes];
            [[expectFutureValue(theValue(fail4)) shouldAfterWaitOf(5)] beYes];

        );
        
    );
    
    context(@"chain request", ^

        it(@"addRequest,request is not a JKBaseRequest", ^
            JKChainRequest *chainRequest = [JKChainRequest new];
            JKBatchRequest *request = [JKBatchRequest new];
            [[theBlock(^
                [chainRequest addRequest:request];
            ) should] raiseWithReason:@"makesure [request isKindOfClass:[JKBaseRequest class]] be YES"];
        );

        it(@"addRequest,request has added in", ^
            JKChainRequest *chainRequest = [JKChainRequest new];
            JKBaseRequest *request = [JKBaseRequest new];
            [chainRequest addRequest:request];
            [[chainRequest.requestArray should] haveCountOf:1];
            [[theBlock(^
                [chainRequest addRequest:request];
            ) should] raiseWithReason:@"request was added"];
        );

        it(@"addRequestsWithArray,array has repeated requests", ^
            JKChainRequest *chainRequest = [JKChainRequest new];
            JKBaseRequest *request = [JKBaseRequest new];
            NSArray *array = @[request,request];
            [[theBlock(^
                [chainRequest addRequestsWithArray:array];
            ) should] raiseWithReason:@"requestArray has duplicated requests"];
        );

        it(@"addRequestsWithArray,array has a request not a JKBaseRequest", ^
            JKChainRequest *chainRequest = [JKChainRequest new];
            JKBaseRequest *request = [JKBaseRequest new];
            JKBatchRequest *batchRequest = [JKBatchRequest new];
            NSArray *array = @[request,batchRequest];
            [[theBlock(^
                [chainRequest addRequestsWithArray:array];
            ) should] raiseWithReason:@"makesure [request isKindOfClass:[JKBaseRequest class]] be YES"];
        );

        it(@"addRequestsWithArray,array has a request add in", ^
            JKChainRequest *chainRequest = [JKChainRequest new];
            JKBaseRequest *request1 = [JKBaseRequest new];
            JKBaseRequest *request2 = [JKBaseRequest new];
            [chainRequest addRequest:request1];
            NSArray *array = @[request1,request2];
            [[theBlock(^
                [chainRequest addRequestsWithArray:array];
            ) should] raiseWithReason:@"requestArray has common request with the added requests"];
        );

        it(@"addRequestsWithArray,normal", ^
            JKChainRequest *chainRequest = [JKChainRequest new];
            JKBaseRequest *request1 = [JKBaseRequest new];
            JKBaseRequest *request2 = [JKBaseRequest new];
            NSArray *array = @[request1,request2];
            [chainRequest addRequestsWithArray:array];
            [[chainRequest.requestArray should] haveCountOf:2];
        );

        it(@"all requests success", ^
            JKChainRequest *chainRequest = [JKChainRequest new];
            JKBaseRequest *request1 = [JKBaseRequest new];
            request1.requestUrl = @"/a1";
            request1.requestSerializerType = JKRequestSerializerTypeHTTP;
            request1.responseSerializerType = JKResponseSerializerTypeJSON;
            __block BOOL success1 = NO;
            [JKChainRequest configNormalRequest:request1 success:^(__kindof JKBaseRequest * _Nonnull request) 
                success1 = YES;
                [[request should] equal:request1];
             failure:^(__kindof JKBaseRequest * _Nonnull request) 

            ];
            JKBaseRequest *request2 = [JKBaseRequest new];
            request2.requestUrl = @"/a2";
            request2.requestSerializerType = JKRequestSerializerTypeHTTP;
            request2.responseSerializerType = JKResponseSerializerTypeJSON;
            __block BOOL success2 = NO;
            [JKChainRequest configNormalRequest:request2 success:^(__kindof JKBaseRequest * _Nonnull request) 
                success2 = YES;
                [[request should] equal:request2];
             failure:^(__kindof JKBaseRequest * _Nonnull request) 

            ];
            NSArray *array = @[request1,request2];
            [chainRequest addRequestsWithArray:array];
            __block BOOL success3 = NO;
            [chainRequest startWithCompletionSuccess:^(JKChainRequest * _Nonnull chainRequest) 
                success3 = YES;
             failure:^(JKChainRequest * _Nonnull chainRequest) 

            ];

            [[expectFutureValue(theValue(success1)) shouldAfterWaitOf(6)] beYes];
            [[expectFutureValue(theValue(success2)) shouldAfterWaitOf(6)] beYes];
            [[expectFutureValue(theValue(success3)) shouldAfterWaitOf(6)] beYes];
        );

        it(@"a request in requests not first,not last, failed", ^
            JKChainRequest *chainRequest = [JKChainRequest new];
            JKBaseRequest *request1 = [JKBaseRequest new];
            request1.requestUrl = @"/a1";
            request1.requestSerializerType = JKRequestSerializerTypeHTTP;
            request1.responseSerializerType = JKResponseSerializerTypeJSON;
            __block BOOL success1 = NO;
            [JKChainRequest configNormalRequest:request1 success:^(__kindof JKBaseRequest * _Nonnull request) 
                success1 = YES;
             failure:^(__kindof JKBaseRequest * _Nonnull request) 

            ];
            //失败的网络请求
            JKBaseRequest *request2 = [JKBaseRequest new];
            request2.baseUrl = @"https://aacoioio.com";
            request2.requestUrl = @"/aaa";
            request2.requestSerializerType = JKRequestSerializerTypeHTTP;
            request2.responseSerializerType = JKResponseSerializerTypeJSON;
            request2.requestTimeoutInterval = 3;
            __block BOOL fail1 = NO;
            [JKChainRequest configNormalRequest:request2 success:^(__kindof JKBaseRequest * _Nonnull request) 

             failure:^(__kindof JKBaseRequest * _Nonnull request) 
                fail1 = YES;
                [[request should] equal:request2];

            ];

            JKBaseRequest *request3 = [JKBaseRequest new];
            request3.requestUrl = @"/a2";
            request3.requestMethod = JKRequestMethodPOST;
            request3.requestSerializerType = JKRequestSerializerTypeHTTP;
            request3.responseSerializerType = JKResponseSerializerTypeJSON;
            __block BOOL fail2 = NO;
            __block BOOL success2 = NO;
            [JKChainRequest configNormalRequest:request3 success:^(__kindof JKBaseRequest * _Nonnull request) 
                success2 = YES;
             failure:^(__kindof JKBaseRequest * _Nonnull request) 
                fail2 = YES;
            ];

            NSArray *array = @[request1,request2,request3];
            [chainRequest addRequestsWithArray:array];
            __block BOOL fail3 = NO;
            [chainRequest startWithCompletionSuccess:^(JKChainRequest * _Nonnull chainRequest) 

             failure:^(JKChainRequest * _Nonnull chainRequest) 
                fail3 = YES;
                [[expectFutureValue(theValue([chainRequest.failedRequest isEqual:request2])) shouldAfterWaitOf(5)] beYes];
            ];

            [[expectFutureValue(theValue(success1)) shouldAfterWaitOf(5)] beYes];
            [[expectFutureValue(theValue(fail1)) shouldAfterWaitOf(5)] beYes];
            [[expectFutureValue(theValue(fail2)) shouldAfterWaitOf(5)] beNo];
            [[expectFutureValue(theValue(success2)) shouldAfterWaitOf(5)] beNo];
            [[expectFutureValue(theValue(fail3)) shouldAfterWaitOf(5)] beYes];
        );
    );


);

SPEC_END


SPEC_BEGIN(JKNetworkAgentSpec)

describe(@"JKNetworkAgent", ^
    beforeEach(^
#if DEBUG
        AFSecurityPolicy *policy = [AFSecurityPolicy defaultPolicy];
        policy.validatesDomainName = NO;
        policy.allowInvalidCertificates = YES;
        [JKNetworkConfig sharedConfig].securityPolicy = policy;
#endif
        [JKNetworkConfig sharedConfig].baseUrl = @"https://123/mock/17";
        [[JKNetworkAgent sharedAgent] cancelAllRequests];

    );

    it(@"addRequest,request is a single request", ^
        JKBaseRequest *request = [JKBaseRequest new];
        request.requestUrl = @"/a1";
        request.requestSerializerType = JKRequestSerializerTypeHTTP;
        request.responseSerializerType = JKResponseSerializerTypeJSON;
        [[JKNetworkAgent sharedAgent] addRequest:request];
        [[[[JKNetworkAgent sharedAgent] allRequests] should] haveCountOf:1];
        [[theValue([[[JKNetworkAgent sharedAgent] allRequests] containsObject:request]) should] beYes];
    );

    it(@"addRequest,request is not a single request", ^
        JKBaseRequest *request = [JKBaseRequest new];
        request.requestUrl = @"/a1";
        request.requestSerializerType = JKRequestSerializerTypeHTTP;
        request.responseSerializerType = JKResponseSerializerTypeJSON;
        JKBatchRequest *batchRequest = [JKBatchRequest new];
        [batchRequest addRequest:request];
        [[theBlock(^
            [[JKNetworkAgent sharedAgent] addRequest:batchRequest];
        ) should] raiseWithReason:@"please makesure [request isKindOfClass:[JKBaseRequest class]] be YES"];
    );

    it(@"addRequest,request is nil", ^

        [[theBlock(^
            [[JKNetworkAgent sharedAgent] addRequest:nil];
        ) should] raiseWithReason:@"request can't be nil"];
    );

    it(@"cancelRequest,request is nil", ^
        [[theBlock(^
            [[JKNetworkAgent sharedAgent] cancelRequest:nil];
        ) should] raiseWithReason:@"request can't be nil"];
    );

    it(@"cancelRequest,request is a single request", ^
        JKBaseRequest *request = [JKBaseRequest new];
        request.requestUrl = @"/a1";
        request.requestSerializerType = JKRequestSerializerTypeHTTP;
        request.responseSerializerType = JKResponseSerializerTypeJSON;
        [[JKNetworkAgent sharedAgent] addRequest:request];
        [[[[JKNetworkAgent sharedAgent] allRequests] should] haveCountOf:1];
        [[theValue([[[JKNetworkAgent sharedAgent] allRequests] containsObject:request]) should] beYes];
        [[JKNetworkAgent sharedAgent] cancelRequest:request];
        [[[[JKNetworkAgent sharedAgent] allRequests] should] haveCountOf:0];

    );

    it(@"cancelRequest,request is not a single request", ^
        JKBaseRequest *request = [JKBaseRequest new];
        request.requestUrl = @"/a1";
        request.requestSerializerType = JKRequestSerializerTypeHTTP;
        request.responseSerializerType = JKResponseSerializerTypeJSON;
        JKBatchRequest *batchRequest = [JKBatchRequest new];
        [batchRequest addRequest:request];
        [[theBlock(^
            [[JKNetworkAgent sharedAgent] cancelRequest:batchRequest];
        ) should] raiseWithReason:@"please makesure [request isKindOfClass:[JKBaseRequest class]] be YES"];
    );

    it(@"addBatchRequest,request is nil", ^
        [[theBlock(^
            [[JKNetworkAgent sharedAgent] addBatchRequest:nil];
        ) should] raiseWithReason:@"request can't be nil"];
    );

    it(@"addBatchRequest,request is a batchRequest", ^
        JKBatchRequest *batchRequest = [JKBatchRequest new];

        JKBaseRequest *request1 = [JKBaseRequest new];
        request1.requestUrl = @"/a1";
        request1.requestSerializerType = JKRequestSerializerTypeHTTP;
        request1.responseSerializerType = JKResponseSerializerTypeJSON;
        [batchRequest addRequest:request1];
        JKBaseRequest *request2 = [JKBaseRequest new];
        request2.requestUrl = @"/a1";
        request2.requestMethod = JKRequestMethodPOST;
        request2.requestSerializerType = JKRequestSerializerTypeHTTP;
        request2.responseSerializerType = JKResponseSerializerTypeJSON;
        [batchRequest addRequest:request2];
        [[JKNetworkAgent sharedAgent] addBatchRequest:batchRequest];
        [[theValue([[[JKNetworkAgent sharedAgent] allRequests] containsObject:request1]) should] beYes];
        [[theValue([[[JKNetworkAgent sharedAgent] allRequests] containsObject:request2]) should] beYes];
        [[[[JKNetworkAgent sharedAgent] allRequests] should] haveCountOf:2];
    );

    it(@"addBatchRequest,request is not a batchRequest", ^
        JKBaseRequest *request1 = [JKBaseRequest new];
        request1.requestUrl = @"/a1";
        request1.requestSerializerType = JKRequestSerializerTypeHTTP;
        request1.responseSerializerType = JKResponseSerializerTypeJSON;
        [[theBlock(^
            [[JKNetworkAgent sharedAgent] addBatchRequest:request1];
        ) should] raiseWithReason:@"please makesure [request isKindOfClass:[JKBatchRequest class]] be YES"];
    );

    it(@"removeBatchRequest,request is a batchRequest", ^
       JKBatchRequest *batchRequest = [JKBatchRequest new];

       JKBaseRequest *request1 = [JKBaseRequest new];
       request1.requestUrl = @"/a1";
       request1.requestSerializerType = JKRequestSerializerTypeHTTP;
       request1.responseSerializerType = JKResponseSerializerTypeJSON;
       [batchRequest addRequest:request1];
       [[JKNetworkAgent sharedAgent] removeBatchRequest:batchRequest];
       [[[[JKNetworkAgent sharedAgent] allRequests] should] haveCountOf:0];
    );

    it(@"removeBatchRequest,request is nil", ^
        [[theBlock(^
            [[JKNetworkAgent sharedAgent] removeBatchRequest:nil];
        ) should] raiseWithReason:@"request can't be nil"];
    );

    it(@"removeBatchRequest,request is not a batchREquest", ^

        JKBaseRequest *request1 = [JKBaseRequest new];
        request1.requestUrl = @"/a1";
        request1.requestSerializerType = JKRequestSerializerTypeHTTP;
        request1.responseSerializerType = JKResponseSerializerTypeJSON;
        [[theBlock(^
            [[JKNetworkAgent sharedAgent] removeBatchRequest:request1];
        ) should] raiseWithReason:@"please makesure [request isKindOfClass:[JKBatchRequest class]] be YES"];
    );

    it(@"addChainRequest,request is nil", ^
        [[theBlock(^
            [[JKNetworkAgent sharedAgent] addChainRequest:nil];
        ) should] raiseWithReason:@"request can't be nil"];
    );

    it(@"addChainRequest,request is a chainRequest", ^
        JKChainRequest *chainRequest = [JKChainRequest new];
        JKBaseRequest *request1 = [JKBaseRequest new];
        request1.requestUrl = @"/a1";
        request1.requestSerializerType = JKRequestSerializerTypeHTTP;
        request1.responseSerializerType = JKResponseSerializerTypeJSON;
        __block BOOL success1 = NO;
        [JKChainRequest configNormalRequest:request1 success:^(__kindof JKBaseRequest * _Nonnull request) 
            success1 = YES;
            [[request should] equal:request1];
         failure:^(__kindof JKBaseRequest * _Nonnull request) 

        ];
        JKBaseRequest *request2 = [JKBaseRequest new];
        request2.requestUrl = @"/a2";
        request2.requestSerializerType = JKRequestSerializerTypeHTTP;
        request2.responseSerializerType = JKResponseSerializerTypeJSON;
        __block BOOL success2 = NO;
        [JKChainRequest configNormalRequest:request2 success:^(__kindof JKBaseRequest * _Nonnull request) 
            success2 = YES;
            [[request should] equal:request2];
         failure:^(__kindof JKBaseRequest * _Nonnull request) 

        ];
        NSArray *array = @[request1,request2];
        [chainRequest addRequestsWithArray:array];
        [[JKNetworkAgent sharedAgent] addChainRequest:chainRequest];
        [[[[JKNetworkAgent sharedAgent] allRequests] should] haveCountOf:3];
        [[JKNetworkAgent sharedAgent] removeChainRequest:chainRequest];

    );

    it(@"addChainRequest,request is not a chainRequest", ^
        JKBaseRequest *request1 = [JKBaseRequest new];
        request1.requestUrl = @"/a1";
        request1.requestSerializerType = JKRequestSerializerTypeHTTP;
        request1.responseSerializerType = JKResponseSerializerTypeJSON;
        [[theBlock(^
            [[JKNetworkAgent sharedAgent] addChainRequest:request1];
        ) should] raiseWithReason:@"please makesure [request isKindOfClass:[JKChainRequest class]] be YES"];
    );

    it(@"removeChainRequest,request is a chainRequest", ^
        JKChainRequest *chainRequest = [JKChainRequest new];
        JKBaseRequest *request1 = [JKBaseRequest new];
        request1.requestUrl = @"/a1";
        request1.requestSerializerType = JKRequestSerializerTypeHTTP;
        request1.responseSerializerType = JKResponseSerializerTypeJSON;
        __block BOOL success1 = NO;
        [JKChainRequest configNormalRequest:request1 success:^(__kindof JKBaseRequest * _Nonnull request) 
            success1 = YES;
            [[request should] equal:request1];
         failure:^(__kindof JKBaseRequest * _Nonnull request) 

        ];
        JKBaseRequest *request2 = [JKBaseRequest new];
        request2.requestUrl = @"/a2";
        request2.requestSerializerType = JKRequestSerializerTypeHTTP;
        request2.responseSerializerType = JKResponseSerializerTypeJSON;
        __block BOOL success2 = NO;
        [JKChainRequest configNormalRequest:request2 success:^(__kindof JKBaseRequest * _Nonnull request) 
            success2 = YES;
            [[request should] equal:request2];
         failure:^(__kindof JKBaseRequest * _Nonnull request) 

        ];
        NSArray *array = @[request1,request2];
        [chainRequest addRequestsWithArray:array];
        [[JKNetworkAgent sharedAgent] addChainRequest:chainRequest];
        [[[[JKNetworkAgent sharedAgent] allRequests] should] haveCountOf:3];
        [[JKNetworkAgent sharedAgent] removeChainRequest:chainRequest];
        [[[[JKNetworkAgent sharedAgent] allRequests] should] haveCountOf:0];
    );

    it(@"removeChainRequest,request is nil", ^

        [[theBlock(^
            [[JKNetworkAgent sharedAgent] removeChainRequest:nil];
        ) should] raiseWithReason:@"request can't be nil"];
    );

    it(@"removeChainRequest,request is not a chainRequest", ^
        JKBaseRequest *request1 = [JKBaseRequest new];
        request1.requestUrl = @"/a1";
        request1.requestSerializerType = JKRequestSerializerTypeHTTP;
        request1.responseSerializerType = JKResponseSerializerTypeJSON;
        [[theBlock(^
            [[JKNetworkAgent sharedAgent] removeChainRequest:request1];
        ) should] raiseWithReason:@"please makesure [request isKindOfClass:[JKChainRequest class]] be YES"];
    );

    it(@"addPriorityFirstRequest,request is nil", ^
        [[theBlock(^
            [[JKNetworkAgent sharedAgent] addPriorityFirstRequest:nil];
        ) should] raiseWithReason:@"request can't be nil"];
    );

    it(@"addPriorityFirstRequest,request is unsupported", ^
        [[theBlock(^
            [[JKNetworkAgent sharedAgent] addPriorityFirstRequest:[NSObject new]];
        ) should] raiseWithReason:@"no support this request as a PriorityFirstRequest"];
    );

    it(@"addPriorityFirstRequest,has request started", ^
        JKBaseRequest *request1 = [JKBaseRequest new];
        request1.requestUrl = @"/a1";
        request1.requestSerializerType = JKRequestSerializerTypeHTTP;
        request1.responseSerializerType = JKResponseSerializerTypeJSON;
        [[JKNetworkAgent sharedAgent] addRequest:request1];
        JKBaseRequest *request2 = [JKBaseRequest new];
        request2.requestUrl = @"/a2";
        request2.requestSerializerType = JKRequestSerializerTypeHTTP;
        request2.responseSerializerType = JKResponseSerializerTypeJSON;

        [[theBlock(^
            [[JKNetworkAgent sharedAgent] addPriorityFirstRequest:request2];
        ) should] raiseWithReason:@"addPriorityFirstRequest func must use before any request started"];
    );

    it(@"addPriorityFirstRequest,request is a single request, success", ^
        JKBaseRequest *request1 = [JKBaseRequest new];
        request1.requestUrl = @"/a1";
        request1.requestSerializerType = JKRequestSerializerTypeHTTP;
        request1.responseSerializerType = JKResponseSerializerTypeJSON;
        [[JKNetworkAgent sharedAgent] addPriorityFirstRequest:request1];

        JKBaseRequest *request2 = [JKBaseRequest new];
        request2.requestUrl = @"/a2";
        request2.requestSerializerType = JKRequestSerializerTypeHTTP;
        request2.responseSerializerType = JKResponseSerializerTypeJSON;
        __block BOOL success1 = NO;
        __block BOOL success2 = NO;
        [request2 startWithCompletionSuccess:^(__kindof JKBaseRequest * _Nonnull request) 
            success2 = YES;
            [[theValue(success1) should] beYes];
         failure:^(__kindof JKBaseRequest * _Nonnull request) 

        ];
        [request1 startWithCompletionSuccess:^(__kindof JKBaseRequest * _Nonnull request) 
            success1 = YES;
            [[theValue(success2) should] beNo];
         failure:^(__kindof JKBaseRequest * _Nonnull request) 

        ];
        [[expectFutureValue(theValue(success1)) shouldAfterWaitOf(3)] beYes];
        [[expectFutureValue(theValue(success2)) shouldAfterWaitOf(3)] beYes];
    );

    it(@"addPriorityFirstRequest,request is a single request, fail", ^

        JKBaseRequest *request1 = [JKBaseRequest new];
        request1.baseUrl = @"https://aacoioio.com";
        request1.requestUrl = @"/aaa1";
        request1.requestSerializerType = JKRequestSerializerTypeHTTP;
        request1.responseSerializerType = JKResponseSerializerTypeJSON;
        request1.requestTimeoutInterval = 3;

        JKBaseRequest *request2 = [JKBaseRequest new];
        request2.requestUrl = @"/a1";
        request2.requestSerializerType = JKRequestSerializerTypeHTTP;
        request2.responseSerializerType = JKResponseSerializerTypeJSON;
        [[JKNetworkAgent sharedAgent] addPriorityFirstRequest:request1];

        __block BOOL success1 = NO;
        __block BOOL success2 = NO;
        __block BOOL fail1 = NO;
        __block BOOL fail2 = NO;
        [request2 startWithCompletionSuccess:^(__kindof JKBaseRequest * _Nonnull request) 
            success2 = YES;
            [[theValue(success1) should] beYes];
         failure:^(__kindof JKBaseRequest * _Nonnull request) 
            fail2 = YES;
        ];
        [request1 startWithCompletionSuccess:^(__kindof JKBaseRequest * _Nonnull request) 
            success1 = YES;
            [[theValue(success2) should] beNo];
         failure:^(__kindof JKBaseRequest * _Nonnull request) 
            fail1 = YES;
        ];
        [[expectFutureValue(theValue(success1)) shouldAfterWaitOf(5)] beNo];
        [[expectFutureValue(theValue(success2)) shouldAfterWaitOf(5)] beNo];
        [[expectFutureValue(theValue(fail1)) shouldAfterWaitOf(5)] beYes];
        [[expectFutureValue(theValue(fail2)) shouldAfterWaitOf(5)] beNo];
    );

    it(@"addPriorityFirstRequest,request is a batchRequest,success", ^
        JKBatchRequest *batchRequest = [JKBatchRequest new];

        JKBaseRequest *request1 = [JKBaseRequest new];
        request1.requestUrl = @"/a1";
        request1.requestSerializerType = JKRequestSerializerTypeHTTP;
        request1.responseSerializerType = JKResponseSerializerTypeJSON;

        JKBaseRequest *request2 = [JKBaseRequest new];
        request2.requestUrl = @"/a2";
        request2.requestMethod = JKRequestMethodPOST;
        request2.requestSerializerType = JKRequestSerializerTypeHTTP;
        request2.responseSerializerType = JKResponseSerializerTypeJSON;
        [batchRequest addRequestsWithArray:@[request1,request2]];

        [[JKNetworkAgent sharedAgent] addPriorityFirstRequest:batchRequest];

        JKBaseRequest *request3 = [JKBaseRequest new];
        request3.requestUrl = @"/a1";
        request3.requestSerializerType = JKRequestSerializerTypeHTTP;
        request3.responseSerializerType = JKResponseSerializerTypeJSON;

        __block BOOL success1 = NO;
        __block BOOL success2 = NO;
        [request3 startWithCompletionSuccess:^(__kindof JKBaseRequest * _Nonnull request) 
            success2 = YES;
            [[theValue(success1) should] beYes];
         failure:^(__kindof JKBaseRequest * _Nonnull request) 

        ];

        [batchRequest startWithCompletionSuccess:^(JKBatchRequest * _Nonnull batchRequest) 
            success1 = YES;
            [[theValue(success2) should] beNo];
         failure:^(JKBatchRequest * _Nonnull batchRequest) 

        ];

       [[expectFutureValue(theValue(success1)) shouldAfterWaitOf(3)] beYes];
        [[expectFutureValue(theValue(success2)) shouldAfterWaitOf(3)] beYes];

    );

    it(@"addPriorityFirstRequest,request is a batchRequest,fail", ^

      JKBatchRequest *batchRequest = [JKBatchRequest new];

      JKBaseRequest *request1 = [JKBaseRequest new];
      request1.baseUrl = @"https://aacoioio.com";
      request1.requestUrl = @"/aaa1";
      request1.requestSerializerType = JKRequestSerializerTypeHTTP;
      request1.responseSerializerType = JKResponseSerializerTypeJSON;
      request1.requestTimeoutInterval = 3;

      JKBaseRequest *request2 = [JKBaseRequest new];
      request2.requestUrl = @"/a2";
      request2.requestMethod = JKRequestMethodPOST;
      request2.requestSerializerType = JKRequestSerializerTypeHTTP;
      request2.responseSerializerType = JKResponseSerializerTypeJSON;
      [batchRequest addRequestsWithArray:@[request1,request2]];

      [[JKNetworkAgent sharedAgent] addPriorityFirstRequest:batchRequest];


      JKBaseRequest *request3 = [JKBaseRequest new];
      request3.requestUrl = @"/a1";
      request3.requestSerializerType = JKRequestSerializerTypeHTTP;
      request3.responseSerializerType = JKResponseSerializerTypeJSON;

      __block BOOL success1 = NO;
      __block BOOL success2 = NO;
      __block BOOL fail1 = NO;
      __block BOOL fail2 = NO;
      [request3 startWithCompletionSuccess:^(__kindof JKBaseRequest * _Nonnull request) 
          success2 = YES;
       failure:^(__kindof JKBaseRequest * _Nonnull request) 
          fail2 = YES;
      ];

      [batchRequest startWithCompletionSuccess:^(JKBatchRequest * _Nonnull batchRequest) 
          success1 = YES;
       failure:^(JKBatchRequest * _Nonnull batchRequest) 
          fail1 = YES;
      ];

      [[expectFutureValue(theValue(success1)) shouldAfterWaitOf(5)] beNo];
      [[expectFutureValue(theValue(success2)) shouldAfterWaitOf(5)] beNo];
      [[expectFutureValue(theValue(fail1)) shouldAfterWaitOf(5)] beYes];
      [[expectFutureValue(theValue(fail2)) shouldAfterWaitOf(5)] beNo];
    );

    it(@"addPriorityFirstRequest,request is a chainRequest,success", ^
        JKChainRequest *chainRequest = [JKChainRequest new];

        JKBaseRequest *request1 = [JKBaseRequest new];
        request1.requestUrl = @"/a1";
        request1.requestSerializerType = JKRequestSerializerTypeHTTP;
        request1.responseSerializerType = JKResponseSerializerTypeJSON;

        JKBaseRequest *request2 = [JKBaseRequest new];
        request2.requestUrl = @"/a2";
        request2.requestMethod = JKRequestMethodPOST;
        request2.requestSerializerType = JKRequestSerializerTypeHTTP;
        request2.responseSerializerType = JKResponseSerializerTypeJSON;
        [chainRequest addRequestsWithArray:@[request1,request2]];

        JKBaseRequest *request3 = [JKBaseRequest new];
        request3.requestUrl = @"/a1";
        request3.requestSerializerType = JKRequestSerializerTypeHTTP;
        request3.responseSerializerType = JKResponseSerializerTypeJSON;
        [[JKNetworkAgent sharedAgent] addPriorityFirstRequest:chainRequest];

        __block BOOL success1 = NO;
        __block BOOL success2 = NO;
        [request3 startWithCompletionSuccess:^(__kindof JKBaseRequest * _Nonnull request) 
            success2 = YES;
            [[theValue(success1) should] beYes];
         failure:^(__kindof JKBaseRequest * _Nonnull request) 

        ];

        [chainRequest startWithCompletionSuccess:^(JKChainRequest * _Nonnull chainRequest) 
            success1 = YES;
            [[theValue(success2) should] beNo];
         failure:^(JKChainRequest * _Nonnull chainRequest) 

        ];

         [[expectFutureValue(theValue(success1)) shouldAfterWaitOf(3)] beYes];
         [[expectFutureValue(theValue(success2)) shouldAfterWaitOf(3)] beYes];
    );

    it(@"addPriorityFirstRequest,request is a chainRequest,fail", ^
        JKChainRequest *chainRequest = [JKChainRe

以上是关于JKNetworking 升级之JKBatchRequest优化升级的主要内容,如果未能解决你的问题,请参考以下文章

JKNetworking完整文档

自动化升级工具之客户端升级工具之数据库升级操作

安卓开发实战之app之版本更新升级(DownloadManager和http下载)完整实现

安卓开发实战之app之版本更新升级(DownloadManager和http下载)完整实现

华为HCIE云计算之FA升级流程

Java锁synchronized关键字学习系列之偏向锁升级