文档章节

一个页面中有多个网络请求时,怎么写比较合理?

 王素年
发布于 2017/07/12 07:34
字数 1265
阅读 37
收藏 1

一、2个请求没有依赖性,但是要求2个请求都完成后才能刷新UI。

二、2个请求有依赖性,A请求完成后,B请求需要用到 A 返回的结果  作为参数进行请求。

 

先解决第一个:

使用GCD的 group ,等两个请求都完成后,在刷新UI.代码如下:

- (void)request{
    
//创建一个GCD group
    self.group = dispatch_group_create();
    
//将请求放入group中处理
    dispatch_group_async(self.group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        [self request1];
    });
    
    dispatch_group_async(self.group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        [self request2];
    });
    
    dispatch_group_async(self.group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        [self request3];
    });
    
//监听group中任务是否都完成了,完成了就执行刷新界面
    dispatch_group_notify(self.group, dispatch_get_main_queue(), ^{
        NSLog(@"刷新界面");
    });
}
//请求1
-(void)request1{
    
    AFHTTPSessionManager *manger = [AFHTTPSessionManager manager];
    NSString *url = @"http://v3.wufazhuce.com:8000/api/channel/movie/more/0?platform=ios&version=v4.0.1";
    [manger GET:url parameters:nil progress:^(NSProgress * _Nonnull downloadProgress) {
        
    } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        NSArray *data = responseObject[@"data"];
        for (NSDictionary *dic in data) {
            NSLog(@"请求1---%@",dic[@"id"]);
        }
        

    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {

    }];
}



//请求2
-(void)request2{
    
    AFHTTPSessionManager *manger = [AFHTTPSessionManager manager];
    NSString *url = @"http://v3.wufazhuce.com:8000/api/channel/movie/more/0?platform=ios&version=v4.0.1";
    [manger GET:url parameters:nil progress:^(NSProgress * _Nonnull downloadProgress) {
        
    } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        NSArray *data = responseObject[@"data"];
        for (NSDictionary *dic in data) {
            NSLog(@"请求2---%@",dic[@"id"]);
        }
        

    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        

    }];
}



//请求3
-(void)request3{
    
    AFHTTPSessionManager *manger = [AFHTTPSessionManager manager];
    NSString *url = @"http://v3.wufazhuce.com:8000/api/channel/movie/more/0?platform=ios&version=v4.0.1";
    [manger GET:url parameters:nil progress:^(NSProgress * _Nonnull downloadProgress) {
        
    } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        NSArray *data = responseObject[@"data"];
        for (NSDictionary *dic in data) {
            NSLog(@"请求3---%@",dic[@"id"]);
        }
        

    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        

    }];
}

运行结果:

我擦,说好的先执行group中的任务,等group中的任务都执行完成后,再执行刷新UI的呢?事与愿违啊!

经过查证找出了原因,原因就是:我们的网络请求AFN发送请求也是在异步线程的。上面这种将请求放入group的写法遵守的整组全部执行完毕指的是三个block写的代码直观进行执行完,就算执行完毕。也就是说[self request1] 执行AFN的代码完了,不包含AFN异步请求。  因此会出现这样的结果。

 

改正:

网上有很多人用group 和 信号量来解决这个问题,其实不需要信号量,队列组就能解决了。只要换一种方式将任务加入队列组就行了。

- (void)request{
    
    self.group = dispatch_group_create();
    
    //下面的任务马上要放到group中执行了
    dispatch_group_enter(self.group);
    [self request1];
    
    
    //下面的任务马上要放到group中执行了
    dispatch_group_enter(self.group);
    [self request2];
    
    
    //下面的任务马上要放到group中执行了
    dispatch_group_enter(self.group);
    [self request3];
    
    
    dispatch_group_notify(self.group, dispatch_get_main_queue(), ^{
        NSLog(@"刷新界面");
    });
}
-(void)request1{
    
    
    AFHTTPSessionManager *manger = [AFHTTPSessionManager manager];
    NSString *url = @"http://v3.wufazhuce.com:8000/api/channel/movie/more/0?platform=ios&version=v4.0.1";
    [manger GET:url parameters:nil progress:^(NSProgress * _Nonnull downloadProgress) {
        
    } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        NSArray *data = responseObject[@"data"];
        for (NSDictionary *dic in data) {
            NSLog(@"请求1---%@",dic[@"id"]);
        }
        //任务完成了,该任务从group中移除
        dispatch_group_leave(self.group);
        
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        
        //任务完成了,该任务从group中移除
        dispatch_group_leave(self.group);
    }];
}




-(void)request2{
    
   
    AFHTTPSessionManager *manger = [AFHTTPSessionManager manager];
    NSString *url = @"http://v3.wufazhuce.com:8000/api/channel/movie/more/0?platform=ios&version=v4.0.1";
    [manger GET:url parameters:nil progress:^(NSProgress * _Nonnull downloadProgress) {
        
    } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        NSArray *data = responseObject[@"data"];
        for (NSDictionary *dic in data) {
            NSLog(@"请求2---%@",dic[@"id"]);
        }
        //任务完成了,该任务从group中移除
        dispatch_group_leave(self.group);
        
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        
        //任务完成了,该任务从group中移除
        dispatch_group_leave(self.group);
    }];
}



-(void)request3{
    
    
    AFHTTPSessionManager *manger = [AFHTTPSessionManager manager];
    NSString *url = @"http://v3.wufazhuce.com:8000/api/channel/movie/more/0?platform=ios&version=v4.0.1";
    [manger GET:url parameters:nil progress:^(NSProgress * _Nonnull downloadProgress) {
        
    } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        NSArray *data = responseObject[@"data"];
        for (NSDictionary *dic in data) {
            NSLog(@"请求3---%@",dic[@"id"]);
        }
        
        //任务完成了,该任务从group中移除
        dispatch_group_leave(self.group);
        
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        
        //任务完成了,该任务从group中移除
        dispatch_group_leave(self.group);
    }];
}

这种dispatch_group_enterdispatch_group_leave是成对出现的,当进入一个操作后,在适当的位置加上dispatch_group_leave,比如在这里,进入第一个 enter 执行 request1 操作,那么在这个方法中异步返回的时候(成功或失败)写上 dispatch_gropu_leave,这样就包含了异步的情况。

 

 

二、解决有依赖的两个请求

// 创建一个队列
    NSOperationQueue *queue = [[NSOperationQueue alloc]init];
    
    
    // 创建一个A操作
    NSBlockOperation *operationA = [NSBlockOperation blockOperationWithBlock:^{

        
        [self requestA];
    }];
    
    
    
    // 创建一个B操作
    NSBlockOperation *operationB = [NSBlockOperation blockOperationWithBlock:^{

        [self requestB];
        
    }];
    
    
    //添加依赖 B要在A打印完在进行打印 所以是B依赖于A 那么只需要添加如下代码即可完成
    [operationB addDependency:operationA];
    
    
    // 分别加入到队列中
    [queue addOperation:operationA];
    [queue addOperation:operationB];
-(void)requestA{
    
    
    AFHTTPSessionManager *manger = [AFHTTPSessionManager manager];
    NSString *url = @"http://v3.wufazhuce.com:8000/api/channel/movie/more/0?platform=ios&version=v4.0.1";
    [manger GET:url parameters:nil progress:^(NSProgress * _Nonnull downloadProgress) {
        
    } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        NSArray *data = responseObject[@"data"];
        for (NSDictionary *dic in data) {
            NSLog(@"请求AAA---%@",dic[@"id"]);
        }
        
        
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        
    }];
}


-(void)requestB{
    
    
    AFHTTPSessionManager *manger = [AFHTTPSessionManager manager];
    NSString *url = @"http://v3.wufazhuce.com:8000/api/channel/movie/more/0?platform=ios&version=v4.0.1";
    [manger GET:url parameters:nil progress:^(NSProgress * _Nonnull downloadProgress) {
        
    } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        NSArray *data = responseObject[@"data"];
        for (NSDictionary *dic in data) {
            NSLog(@"请求BBB---%@",dic[@"id"]);
        }
        
        
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        
    }];
}

这里我没有在一个线程请求返回成功后,再发起第二个请求,这种方式也能解决问题,但是这样写代码会比较乱,我不喜欢这么写。

© 著作权归作者所有

共有 人打赏支持
粉丝 2
博文 71
码字总数 44391
作品 0
普陀
程序员
私信 提问
浅谈前端与网络请求

作者:不洗碗工作室 - 张景浩 博客地址:http://michaelcode.cn版权归作者所有,转载请注明出处 toc: 前端 学前端也有一段时间了,想浅谈一下前端与网络请求。谈网络请求,自然绕不开的一个话...

不洗碗工作室
2017/12/08
0
0
解读如何用YSlow分析我们页面

YSlow是yahoo美国开发的一个页面评分插件,非常的棒,从中我们可以看出我们页面上的很多不足,并且可以知道我们改怎么却改进和优化。 仔细研究了下YSlow跌评分规则。 主要有12条: 1. Make ...

挨踢骑术
2011/05/04
0
0
网页优化插件--YSlow

YSlow是yahoo美国开发的一个页面评分插件,非常的棒,从中我们可以看出我们页面上的很多不足,并且可以知道我们改怎么却改进和优化。 YSlow跌评分规则。 主要有12条: 1. Make fewer HTTP r...

匿名
2008/09/19
12.9K
2
Python 实现「食行生鲜」签到领积分

用过食行生鲜的同学应该知道,每天可以在食行生鲜签到,签到可以领到 20 积分,在购物时可以抵 2 毛钱。钱虽少,但是积少成多,买菜时可以抵扣一两块钱还是不错的。 今天我们就用 Python 来实...

不正经程序员
08/02
0
0
分享17点PC浏览器前端优化策略——网络加载篇

PC端优化的策略很多,如 YSlow(YSlow 是 Yahoo 发布的一款 Firefox 插件,现 Chrome 也可安装,可以对网站的页面性能进行分析,提出对该页面性能优化的建议)原则,或者 Chrome 自带的 Audi...

沉迷学习中
2017/11/13
0
0

没有更多内容

加载失败,请刷新页面

加载更多

方之熙博士被任命为RISC-V基金会中国顾问委员会主席,加速RISC-V ISA在中国的应用

中国顾问委员会将就RISC-V基金会的教育和应用推广战略提供指导 今天在中国乌镇举行的世界互联网大会(World Internet Conference)上,RISC-V基金会(RISC-V Foundation)宣布,半导体行业资深人...

whoisliang
25分钟前
1
0
为了用户体验,不要做浏览器兼容

读者看到文章标题也许会感到奇怪,按照通常的经验来说,为了用户体验应该做浏览器兼容,以便让不同的浏览器用户都能有好的体验,从而增加网站的流量,但是我认为做浏览器兼容属于同样的工作重...

Bob2100
26分钟前
1
0
分布式定时任务架构 (二) xxl-job二次开发实践

4个月前,公司有任务调度的需求,需要一周内完成,时间非常紧。 需求有三点: web界面编辑cron表达式,启动,停止任务 接入公司的rpc成本较低,公司有自研的rpc,研发人员希望共用同一套注解 ...

勇哥和你一起学技术
42分钟前
1
0
React和Redux的连接react-redux

通过Redux文档来了解react-redux,在一段时间的实践后准备翻一翻源代码,顺便做些相关的总结。我看的代码的npm版本为v4.0.0,也就是说使用的React版本是0.14.x。 react-redux提供两个关键模块...

前端攻城老湿
今天
1
0
1、Mybatis连接池配置 和 Context.xml的配置

注意: (1)mybatis 3.2 之前 通过 set get 方法 获取相关属性。之后通过属性姓名获取相关关联。 (2)mybatis 映射 优先为 sql 语句中的别名与实体类的属性进行映射。 (3)jndi Java用于调...

KingFightingAn
今天
1
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部