如何处理多个并发的网络请求之间的依赖关系?

有a,b,c,d四个网络请求,如何判断a,b,c,d都执行完毕了?如何让a,b,c,d顺序执行?

之前在网上看到最多的答案就是使用dispatch_group,具体方案是这样:

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_ DEFAULT, 0);


dispatch_group_t group = dispatch_group_create();

dispatch_group_async(group, queue, ^{ /*任务 a */ });

dispatch_group_async(group, queue, ^{ /*任务 b */ });

dispatch_group_async(group, queue, ^{ /* 任务c */ });

dispatch_group_async(group, queue, ^{ /* 任务d */ });

dispatch_group_notify(group,dispatch_get_main_queue(), ^{
// 在a、b、c、d异步执行完成后,会回调到这里

}); 

但是我自己实际实践了之后,发现并不是这样。我的需求场景是这样,我需要下载四张图片,四张图片都下载完成后合成一张图片。我是使用基于AFN封装的网络请求工具类请求下载图片的,只有当请求有回调的时候(不管成功或失败),才能代表这次网络请求执行完毕。而使用上面的方法只能保证网络请求执行了,但并没有回调完成。下面直接上代码说明:

- (void)testGCDAPI {
    
    
    dispatch_group_t group = dispatch_group_create();
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    
    NetWorkBase *netWorkManager = [NetWorkBase new];
    
    dispatch_group_async(group, queue, ^{
        NSLog(@"start1");
        [netWorkManager startGet:IMAGE_TEST_1 parameters:nil withBlock:^(id result, BOOL succ) {
            NSLog(@"回调1");
            _imageView1.image = [UIImage imageWithData:result];
        }];

        
    });
    dispatch_group_async(group, queue, ^{
        
        NSLog(@"start2");
        [netWorkManager startGet:IMAGE_TEST_2 parameters:nil withBlock:^(id result, BOOL succ) {
            NSLog(@"回调2");
            _imageView2.image = [UIImage imageWithData:result];
        }];

    });
    dispatch_group_async(group, queue, ^{
        
        NSLog(@"start3");
        [netWorkManager startGet:IMAGE_TEST_3 parameters:nil withBlock:^(id result, BOOL succ) {
            NSLog(@"回调3");
            _imageView3.image = [UIImage imageWithData:result];


        }];
    });
    
    dispatch_group_async(group, queue, ^{
        NSLog(@"start4");
        [netWorkManager startGet:IMAGE_TEST_4 parameters:nil withBlock:^(id result, BOOL succ) {
            NSLog(@"回调4");
            _imageView4.image = [UIImage imageWithData:result];
        }];
    });
    
    dispatch_group_notify(group, queue, ^{
        NSLog(@"4张图片全都加载完毕");
    });
}

控制台打印效果如下:

可以看出,以上方法并不能保证group_notify里的代码是在网络请求有回调之后再执行。那么如何才能保证group_notify在所有网络请求都有回调之后才调用呢?

我们可以使用变量flag来标识网络请求回调,但是这样不够优雅,也不是使用GCD来实现了。

- (void)testGCDAPI {
    
    
    dispatch_group_t group = dispatch_group_create();
    dispatch_queue_t queue = dispatch_get_main_queue();
    
    NetWorkBase *netWorkManager = [NetWorkBase new];
    
    dispatch_group_enter(group);
    [netWorkManager startGet:IMAGE_TEST_1 parameters:nil withBlock:^(id result, BOOL succ) {
        NSLog(@"回调1");
        _imageView1.image = [UIImage imageWithData:result];
        
        
        dispatch_group_leave(group);

    }];

        
        dispatch_group_enter(group);
        [netWorkManager startGet:IMAGE_TEST_2 parameters:nil withBlock:^(id result, BOOL succ) {
            NSLog(@"回调2");
            _imageView2.image = [UIImage imageWithData:result];
            
            
            dispatch_group_leave(group);

        }];

    
        dispatch_group_enter(group);
        [netWorkManager startGet:IMAGE_TEST_3 parameters:nil withBlock:^(id result, BOOL succ) {
            NSLog(@"回调3");
            _imageView3.image = [UIImage imageWithData:result];
            
            
            dispatch_group_leave(group);
        }];
    
        dispatch_group_enter(group);
        [netWorkManager startGet:IMAGE_TEST_4 parameters:nil withBlock:^(id result, BOOL succ) {
            NSLog(@"回调4");
            _imageView4.image = [UIImage imageWithData:result];
            
            
            dispatch_group_leave(group);
        }];
    
    dispatch_group_notify(group, queue, ^{
        NSLog(@"4张图片全都加载完毕");
    });
}

在每个网络请求开始前使用dispatch_group_enter来进行标识,网络请求有回调后使用dispatch_group_leave来进行标识,这样就能保证group_notify在所有网络请求都有回调之后才调用。而同时也保证了这四个网络请求是顺序执行的

控制台打印效果:

 

 

            

 

posted @ 2017-03-09 17:17  记不住密码  阅读(1208)  评论(0编辑  收藏  举报