美文网首页iOS奋斗ios 进阶开发杂谈
多个网络请求的接口设计

多个网络请求的接口设计

作者: __夏至未至 | 来源:发表于2017-01-04 14:37 被阅读990次

    最近做到一个页面里有四个接口,每一个接口返回都有对应的UI改变,所以要四个接口全部请求返回成功后,再去做UI刷新。然而由于网络请求用的是AFN等第三方库,本身就是异步的,所以GCD的栅栏函数dispatch_barrier_async是没有用的。

    那么就让他一个一个的执行,等到所有都执行完成后再去刷新UI,于是乎呢,可以在第一个网络请求了的返回block里去做第二个网络请求,以此类推就可以完成最后的UI刷新。这个不失为一种比较有效的方法,但是这样写的代码真的挺丑的。。。。

    如果单纯的想让这几个网络请求按顺序执行,先进先出,那就是队列啊,iOS里提供的队列管理就是GCD这个强大的c语言实现的库。GCD里面有一个信号量--dispatch_semaphore_t,

    dispatch_semaphore_t

    dispatch_semaphore_create(long value);创建一个信号量,如果value小于0的话,这个信号量就是nil。
    dispatch_semaphore_wait(dispatch_semaphore_t dsema, dispatch_time_t timeout);可以让信号量减1,如果信号量是0,那么他会等待信号量为非零才会执行下一步。
    dispatch_semaphore_signal(dispatch_semaphore_t dsema);可以让信号量增加1.

    通过这上面的方法,我们可以一开始设计信号量是0,每一个网络请求之前用dispatch_semaphore_wait(dispatch_semaphore_t dsema, dispatch_time_t timeout);,请求结束回调里用dispatch_semaphore_signal(dispatch_semaphore_t dsema);这样可以让请求按照顺序执行下来。Talk is cheep,show your the code:

    - (void)semaphoretest {
        dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
    
        dispatch_async(dispatch_get_global_queue(0, 0), ^{
            sleep(2);
            NSLog(@"任务1完成---- %@", [NSThread currentThread]);
            dispatch_semaphore_signal(semaphore);
        });
    
        dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
        dispatch_async(dispatch_get_global_queue(0, 0), ^{
            sleep(2);
            NSLog(@"任务2完成---- %@", [NSThread currentThread]);
            dispatch_semaphore_signal(semaphore);
        });
    
        dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
        dispatch_async(dispatch_get_global_queue(0, 0), ^{
            sleep(2);
            NSLog(@"任务3完成---- %@", [NSThread currentThread]);
            dispatch_semaphore_signal(semaphore);
        });
    }
    

    打印结果如下:

    信号量结果.png

    很清楚的看到了他们是按照顺序执行的。

    dispatch_group

    最好的设计当然是他们几个并发执行,到时候全部请求结束后再去做UI的刷新。于是乎想到了CGD的group啦!GCD就是辣么强大有木有!设计如下:

    - (void)groupTest {
        dispatch_queue_t quete = dispatch_queue_create("XIAXIAQUEUE", DISPATCH_QUEUE_CONCURRENT);
        dispatch_group_t group = dispatch_group_create();
    
        dispatch_group_enter(group);
        dispatch_group_async(group, quete, ^{
            dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
                sleep(5);
            
                NSLog(@"网络任务1完----%@", [NSThread currentThread]);
                dispatch_group_leave(group);
            });
            sleep(2);
            NSLog(@"任务1完成---%@", [NSThread currentThread]);
        });
    
    //    dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
        dispatch_group_enter(group);
        dispatch_group_async(group, quete, ^{
            dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
                sleep(5);
            
                NSLog(@"网络任务2完成----%@", [NSThread currentThread]);
                dispatch_group_leave(group);
            });
            sleep(2);
            NSLog(@"任务2完成---%@", [NSThread currentThread]);
        
        });
    
    //    dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
        dispatch_group_enter(group);
        dispatch_group_async(group, quete, ^{
            dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
                sleep(5);
            
                NSLog(@"网络任务3完成 --- %@", [NSThread currentThread]);
                dispatch_group_leave(group);
            });
            sleep(2);
            NSLog(@"任务3完成---- %@", [NSThread currentThread]);
        });
    
    
    
        dispatch_group_notify(group, dispatch_get_main_queue(), ^{
            NSLog(@"最后执行 ---- %@", [NSThread currentThread]);
        });
    }
    

    打印的结果如下:

    group结果.png

    首先可以发现其实这几个任务都是在不同的线程的,但是最后执行的肯定是最后一步!

    结束语

    作为一个程序猿,思考是最重要的,虽然现在网上很多代码可以用拿来主义,但是如果只会拿来,那只能作为一个初级的程序猿了。所以有时候多思考,多想想。

    相关文章

      网友评论

      • colbrze:show you the code.
        夏夏女神,你的英文要再学习啦
      • 晨阳聊电影:如果我用那个并发的话,把那个网络请求是放在网络任务1完成还是任务1完成,他两个里面有啥区别?在结束的时候刷新UI是啊
        __夏至未至:网络请求是网络任务1里面 这是为了区分开来
      • 0ef6911e6477:你好,如果使用串行队列,串行队列中添加异步线程 不知道这个方案如何?
        __夏至未至:串行队列添加异步线程其实和主线程里直接用异步线程没有区别的,主线程本来就类似于一个串行队列呀,按顺序从上往下执行。

      本文标题:多个网络请求的接口设计

      本文链接:https://www.haomeiwen.com/subject/kxbovttx.html