Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >浅谈如何在项目中处理页面中的多个网络请求

浅谈如何在项目中处理页面中的多个网络请求

作者头像
s_在路上
发布于 2018-09-11 09:16:31
发布于 2018-09-11 09:16:31
3.5K00
代码可运行
举报
文章被收录于专栏:iOS 开发杂谈iOS 开发杂谈
运行总次数:0
代码可运行

在开发中很多时候会有这样的场景,同一个界面有多个请求,而且要在这几个请求都成功返回的时候再去进行下一操作,对于这种场景,如何来设计请求操作呢?今天我们就来讨论一下有哪几种方案。

分析:

在网络请求的开发中,经常会遇到两种情况,一种是多个请求结束后统一操作,在一个界面需要同时请求多种数据,比如列表数据、广告数据等,全部请求到后再一起刷新界面。另一种是多个请求顺序执行,比如必须先请求个人信息,然后根据个人信息请求相关内容。这些要求对于普通的操作是可以做到并发控制和依赖操作的,但是对于网络请求这种需要时间的请求来说,效果往往与预期的不一样。因为网络请求是异步的,并不知道什么时候网络请求。很多开发人员为了省事,对于网络请求必须满足一定顺序这种情况,一般都是嵌套网络请求,即一个网络请求成功之后再请求另一个网络请求,虽然采用嵌套请求的方式能解决此问题,但存在很多问题,如:其中一个请求失败会导致后续请求无法正常进行、多个请求在时间上没有复用,即无并发性。来看一下下面几种方案:

dispatch_semaphore 信号量

信号量是一个整数,在创建的时候会有一个初始值,这个初始值往往代表我要控制的同时操作的并发数。 在操作中,对信号量会有两种操作:信号通知与等待。信号通知时,信号量会+1,等待时,如果信号量大于0,则会将信号量-1,否则,会等待直到信号量大于0。什么时候会大于零呢?往往是在之前某个操作结束后,我们发出信号通知,让信号量+1。

在 GCD 中,提供了以下这么几个函数,可用于请求同步等处理,模拟同步请求:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 创建一个信号量(semaphore)
dispatch_semaphore_t semaphore = dispatch_semaphore_create(value);
// 等待,直到信号量大于0时,即可操作,同时将信号量-1
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
// 信号通知,即让信号量+1
dispatch_semaphore_signal(semaphore);

在使用的时候,往往会创建一个信号量,然后进行多个操作,每次操作都等待信号量大于0再操作,同时信号量-1,操作完后将信号量+1。当信号量就减小到0了,这时候wait操作会起作用,DISPATCH_TIME_FOREVER 表示会永远等待,一直等到信号量大于0,也就是有操作完成了,将信号量+1了,这时候才可以结束等待,进行操作,并且将信号量-1,这样新的任务又要等待。

下面我们展示一段代码来模拟同步请求:

image.png

从打印结果可以看出,在每个请求开始之前,我们创建一个信号量,初始为0,在请求操作之后,我们设一个 dispatch_semaphore_wait,在请求到结果之后,再将信号量+1,也即是 dispatch_semaphore_signal。这样做的目的是保证在请求结果没有返回之前,一直让线程等待在那里,这样一个线程的任务一直在等待,就不会算作完成,notify 的内容也就不会执行了,直到每个请求的结果都返回了,线程任务才能够结束,这时候 notify 也才能够执行。

dispatch_group(组)

可以使用 dispatch_group_async 函数将多个任务关联到一个 dispatch_group 和相应的 queue 中,dispatch_group 会并发地同时执行这些任务。而且 dispatch_group 可以用来阻塞一个线程,直到 dispatch_group 关联的所有的任务完成执行。有时候必须等待任务完成的结果,然后才能继续后面的处理。

主要使用如下两个函数:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
dispatch_group_enter(group);
dispatch_group_leave(group);

注意: 以上这两个函数必须配对使用,否则 dispatch_group_notify 不会触发。

下面我们展示一段代码来模拟同步请求:

image.png

dispatch_group 会等和它关联的所有的 dispatch_queue_t 上的任务都执行完毕才会发出同步信号,dispathc_group_notify 的代码块 block 会被执行。从控制台的打印结构可以看出,如果将上面三个操作改成真实的网络操作后,这个简单的做法会变得无效,因为网络请求需要时间,而线程的执行并不会等待请求完成后才真正算作完成,而是只负责将请求发出去,线程就认为自己的任务算完成了,当三个请求都发送出去,就会执行 dispathc_group_notify 中的内容,但请求结果返回的时间是不一定的,也就导致界面都刷新了,请求才返回,这就是无效的。

image.png

notify 的作用就是在 group 中的其他操作全部完成后,再操作自己的内容,所以我们会看到上面事件 A、B、C 执行之后,才执行事件 E。 和 dispatch_async 相比,当我们调用 ndispatch_group_enter 后再调用 ndispatch_group_level 时,dispatch_group_notifydispatch_group_wait 会收到同步信号;这个特点使得它非常适合处理异步任务的同步当异步任务开始前调用 dispatch_group_enter 异步任务结束后调用 dispatch_group_leve

NSOperationQueue

NSOperationQueue 只有两种队列,即主队列和并行队列。通过 [[NSOperationQueue alloc] init]; 创建的队列都是并行队列,并且可以将一个或多个 NSOperation 对象放到队列中去执行,而且是异步执行的,一个 NSOperation 对象可以通过调用 start 方法来执行任务,但是默认是同步执行的。则主队列通过 [NSOperationQueue mainQueue]; 获得,而且其中所有 NSOperation 都会在主线程中执行。

当然也可以利用 NSOperationQueue 的线程依赖,当某个 NSOperation 对象依赖于其它 NSOperation 对象的完成时,就可以通过 addDependency 方法添加一个或者多个依赖的对象,只有所有依赖的对象都已经完成操作,当前 NSOperation 对象才会开始执行操作。需要先添加依赖关系,再将操作添加到队列中。另外,通过 removeDependency 方法来删除依赖对象。

结论

在开发过程中,我们应尽量避免发送同步请求;假设我们一个页面需要同时进行多个请求,他们之间倒是不要求顺序关系,但是要求等他们都请求完毕了再进行界面刷新或者其他什么操作。并且在某个操作依赖于其他几个任务的完成时,采用 dispatch_group or dispatch_semaphore 来实现同步等处理。如果在某个操作依赖于其他几个任务的完成,可以考虑使用 NSOperationQueue 的线程之间依赖。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2016.06.15 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
怎么解决网络请求的依赖关系
怎么解决网络请求的依赖关系:当一个接口的请求需要依赖于另一个网络请求的结果 思路1:操作依赖:NSOperation 操作依赖和优先级(不适用,异步网络请求并不是立刻返回,无法保证回调时再开启下一个网络请求) [operationB addDependency:operationA]; // 操作B依赖于操作 思路2:逻辑判断:在上一个网络请求的响应回调中进行下一网络请求的激活(不适用,可能拿不到回调) 思路3:线程同步 -- 组队列(dispatch_group) dispatch_queue_t que
陈满iOS
2018/09/10
9290
iOS之利用GCD信号量控制并发网络请求
对计算机了解的都会知道信号量的作用,当我们多个线程要访问同一个资源的时候,往往会设置一个信号量,当信号量大于0的时候,新的线程可以去操作这个资源,操作时信号量-1,操作完后信号量+1,当信号量等于0的时候,必须等待,所以通过控制信号量,我们可以控制能够同时进行的并发数。
Cloudox
2022/01/07
1.7K0
iOS多个网络请求完成后执行下一步
在开发中,我们很容易遇到这样的需求,需要我们同时做多个网络请求,所有网络请求都完成后才能进行下一步的操作。如下载多个图片,下载完了才能展示。 今天我们就来研究一下这个问题的解决方案。 1.首先,我们创建一个项目,然后做一般性的做法,不做任何处理去连续请求一个接口10次: 先在viewDidLoad中创建第一种情况. //1.无处理 UIButton *Btn1 = [UIButton buttonWithType:UIButtonTypeCustom]; Btn1.frame = CGRec
清墨
2018/05/07
3K0
关于GCD同步组实现多个异步线程的同步执行中的注意点
在App开发中经常会遇到多个线程同时向服务器取数据, 如果每个线程取得数据后都去刷新UI会造成界面的闪烁
周希
2019/10/15
3.2K0
多线程-GCD
GCD是苹果为多核的并行运算提出的解决方案,所以会自动合理地利用更多的CPU内核(比如双核、四核),最重要的是它会自动管理线程的生命周期(创建线程、调度任务、销毁线程),完全不需要我们管理,我们只需要告诉干什么就行。同时GCD抽象层次最高,当然是用起来也最简单,只是它基于C语言开发,并不像NSOperation是面向对象的开发,而是完全面向过程的。
進无尽
2018/09/12
1.2K0
GCD信号量-dispatch_semaphore_t
1.GCD信号量简介 GCD信号量机制主要涉及到以下三个函数: dispatch_semaphore_create(long value); // 创建信号量 dispatch_semaphore_signal(dispatch_semaphore_t deem); // 发送信号量 dispatch_semaphore_wait(dispatch_semaphore_t dsema, dispatch_time_t timeout); // 等待信号量 dispatch_semaphore_create(
VV木公子
2018/06/05
8.7K0
iOS 面试之多线程
死锁是由于多个线程(进程)在执行过程中,因为争夺资源而造成的互相等待现象,你可以理解为卡主了。产生死锁的必要条件有四个:
赵哥窟
2020/06/19
6910
GCD梳理与总结-常用API操练
定时器 GCD的定时器比NSTimer有更高的进度,而且避免了NSTimer的三大缺陷(RunLoop,不能跨越线程操作,内存泄漏风险)
ios-lan
2020/10/26
3600
GCD梳理与总结-常用API操练
iOS 多线程总结
●进程是指在系统中正在运行的一个应用程序,就是一段程序的执行过程,我们可以理解为手机上的一个app。 ●每个进程之间是独立的,每个进程均运行在其专用且受保护的内存空间内,拥有独立运行所需的全部资源。
赵哥窟
2019/09/27
7660
阿里、字节:一套高效的iOS面试题( 多线程 GCD底层原理篇)
dispatch_group_create() + dispatch_group_wait()
会写bug的程序员
2020/06/18
4.8K0
阿里、字节:一套高效的iOS面试题( 多线程 GCD底层原理篇)
iOS学习——(转)多线程
转载自:iOS多线程全套:线程生命周期,多线程的四种解决方案,线程安全问题,GCD的使用,NSOperation的使用
mukekeheart
2018/08/01
1.2K0
iOS学习——(转)多线程
iOS 多线程:『GCD』详尽总结(二)
同步执行 + 主队列在不同线程中调用结果也是不一样,在主线程中调用会出现死锁,而在其他线程中则不会。
iOSSir
2023/03/19
6871
iOS 多线程:『GCD』详尽总结(二)
AFNetworing同步网络请求?
今天遇到了一个有关同步网络请求的需求是这样的,App中所有网络请求都需要使用一个BaseUrl作为前缀,这个前缀需要一个专门的配置接口去请求获取。考虑到如果在App启动的时候异步请求配置接口获取BaseUrl,并不能保证APP首页发起的网络请求前缀是正确的BaseUrl,于是我考虑采用同步请求的方法确保BaseUrl的获取。 因为我们在开发App的时候常用的网络框架就是AFNetWorking ,于是我首先想到了使用AFNetworking结合信号量的方式来实现这个同步请求,代码如下: //更新系统配置,获
梧雨北辰
2018/04/24
1.5K0
iOS多线程的初步研究-- dispatch同步
dispatch_group_t group = dispatch_group_create();
freesan44
2018/09/05
8380
OC底层探索23-GCD(下)OC底层探索23-GCD(下)
在上篇OC底层探索22-GCD(上)中分析了GCD的串/并队列的创建,同步、异步函数执行,而且留下了:死锁、栅栏函数的坑会在本文中补上;
用户8893176
2021/08/09
3500
OC底层探索23-GCD(下)OC底层探索23-GCD(下)
iOS多线程:『GCD』详尽总结
本文首发于我的个人博客:『不羁阁』 文章链接:传送门 本文更新时间:2018-02-24 10:07:40 感谢大家对这篇文章的喜欢和支持。为了不辜负大家的喜欢,也为了更好的让大家了解 iOS 多线程,以及 GCD 的相关知识,我对这篇文章进行了重新梳理,在原有文章的基础上修改了原文存在的问题,并增加了更多关于 GCD 相关知识和使用方法,希望大家能够喜欢这篇新文章。 本文用来介绍 iOS 多线程中 GCD 的相关知识以及使用方法。这大概是史上最详细、清晰的关于 GCD 的详细讲解+总结的文
程序员充电站
2018/05/31
1K0
多线程(二):GCD
同步添加,将指定的任务block同步追加到queue中,在追加的block结束之前,dispatch_sync会一直等待;
Helloted
2022/06/07
4290
多线程(二):GCD
iOS OC你了解的锁有哪些
synchronized是互斥锁,在这里主要考虑的是线程安全的问题,使用这个关键字,可以将一段代码限制在一个线程内使用,如果有一个线程正在使用这块资源,那么别的线程想要使用的时候就必须等待这快线程执行完毕!
赵哥窟
2020/06/23
1.1K0
iOS开发之再探多线程编程:Grand Central Dispatch详解
Swift3.0相关代码已在github上更新。之前关于iOS开发多线程的内容发布过一篇博客,其中介绍了NSThread、操作队列以及GCD,介绍的不够深入。今天就以GCD为主题来全面的总结一下GCD的使用方式。GCD的历史以及好处在此就不做过多的赘述了。本篇博客会通过一系列的实例来好好的总结一下GCD。GCD在iOS开发中还是比较重要的,使用场景也是非常多的,处理一些比较耗时的任务时基本上都会使用到GCD, 在使用是我们也要主要一些线程安全也死锁的东西。 本篇博客中对iOS中的GCD技术进行了较为全面的总
lizelu
2018/01/11
8280
iOS开发之再探多线程编程:Grand Central Dispatch详解
iOS多线程之GCD、OperationQueue 对比和实践记录
在计算的早期,计算机可以执行的最大工作量是由 CPU 的时钟速度决定的。但是随着技术的进步和处理器设计的紧凑化,热量和其他物理约束开始限制处理器的最大时钟速度。因此,芯片制造商寻找其他方法来提高芯片的总体性能。他们决定的解决方案是增加每个芯片上的处理器核心数量。通过增加内核的数量,一个单独的芯片可以每秒执行更多的指令,而不用增加 CPU 的速度或改变芯片的大小或热特性。唯一的问题是如何利用额外的内核。
woopDast1
2020/09/04
1.6K1
iOS多线程之GCD、OperationQueue 对比和实践记录
相关推荐
怎么解决网络请求的依赖关系
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验