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


    有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在所有网络请求都有回调之后才调用。而同时也保证了这四个网络请求是顺序执行的

    控制台打印效果:

                

  • 相关阅读:
    python __path__ 变量
    mysql-5.7.9 shutdown 语法详解
    scikit-learn随机森林调参小结
    supervisor安装部署文档和管理实例
    随机森林种类及区别--g1
    决策树算法原理--good blog
    各种排序算法的时间复杂度
    【Django2.0】python manage.py makemigrations 和 python manage.py migrate的区别
    使用Apollo做配置中心
    lock in share mode 和 select for update
  • 原文地址:https://www.cnblogs.com/i-am-lvjiazhen/p/6526667.html
Copyright © 2020-2023  润新知