iOS面试题--如何在项目中处理页面中的多个网络请求
2017-10-25 10:31
651 查看
面试题:
如何在项目中处理页面中的多个网络请求。
在开发中很多时候会有这样的场景,同一个界面有多个请求,而且要在这几个请求都成功返回的时候再去进行下一操作,对于这种场景,如何来设计请求操作呢?今天我们就来讨论一下有哪几种方案。
分析:
在网络请求的开发中,经常会遇到两种情况,一种是多个请求结束后统一操作,在一个界面需要同时请求多种数据,比如列表数据、广告数据等,全部请求到后再一起刷新界面。另一种是多个请求顺序执行,比如必须先请求个人信息,然后根据个人信息请求相关内容。这些要求对于普通的操作是可以做到并发控制和依赖操作的,但是对于网络请求这种需要时间的请求来说,效果往往与预期的不一样。因为网络请求是异步的,并不知道什么时候网络请求。很多开发人员为了省事,对于网络请求必须满足一定顺序这种情况,一般都是嵌套网络请求,即一个网络请求成功之后再请求另一个网络请求,总觉得这么不做不是一个好的解决方案,来看一下下面几种方案:
dispatch_semaphore_create:创建一个信号量(semaphore)
dispatch_semaphore_signal:信号通知,即让信号量+1
dispatch_semaphore_wait:等待,直到信号量大于0时,即可操作,同时将信号量-1
在使用的时候,往往会创建一个信号量,然后进行多个操作,每次操作都等待信号量大于0再操作,同时信号量-1,操作完后将信号量+1。当信号量就减小到0了,这时候wait操作会起作用,
当然也可以利用
多个请求结束后统一操作,最优方案:
假设我们一个页面需要同时进行多个请求,他们之间倒是不要求顺序关系,但是要求等他们都请求完毕了再进行界面刷新或者其他什么操作。
一、dispatch_group_t
image.png
image.png
和
二、dispatch_semaphore_t
image.png
在每个请求开始之前,我们创建一个信号量,初始为0,在请求操作之后,我们设一个
如何在项目中处理页面中的多个网络请求。
在开发中很多时候会有这样的场景,同一个界面有多个请求,而且要在这几个请求都成功返回的时候再去进行下一操作,对于这种场景,如何来设计请求操作呢?今天我们就来讨论一下有哪几种方案。
分析:
在网络请求的开发中,经常会遇到两种情况,一种是多个请求结束后统一操作,在一个界面需要同时请求多种数据,比如列表数据、广告数据等,全部请求到后再一起刷新界面。另一种是多个请求顺序执行,比如必须先请求个人信息,然后根据个人信息请求相关内容。这些要求对于普通的操作是可以做到并发控制和依赖操作的,但是对于网络请求这种需要时间的请求来说,效果往往与预期的不一样。因为网络请求是异步的,并不知道什么时候网络请求。很多开发人员为了省事,对于网络请求必须满足一定顺序这种情况,一般都是嵌套网络请求,即一个网络请求成功之后再请求另一个网络请求,总觉得这么不做不是一个好的解决方案,来看一下下面几种方案:
信号量
信号量是一个整数,在创建的时候会有一个初始值,这个初始值往往代表我要控制的同时操作的并发数。在操作中,对信号量会有两种操作:信号通知与等待。信号通知时,信号量会+1,等待时,如果信号量大于0,则会将信号量-1,否则,会等待直到信号量大于0。什么时候会大于零呢?往往是在之前某个操作结束后,我们发出信号通知,让信号量+1。dispatch_semaphore_create:创建一个信号量(semaphore)
dispatch_semaphore_signal:信号通知,即让信号量+1
dispatch_semaphore_wait:等待,直到信号量大于0时,即可操作,同时将信号量-1
在使用的时候,往往会创建一个信号量,然后进行多个操作,每次操作都等待信号量大于0再操作,同时信号量-1,操作完后将信号量+1。当信号量就减小到0了,这时候wait操作会起作用,
DISPATCH_TIME_FOREVER表示会永远等待,一直等到信号量大于0,也就是有操作完成了,将信号量+1了,这时候才可以结束等待,进行操作,并且将信号量-1,这样新的任务又要等待。
NSOperationQueue
NSOperationQueue只有两种队列,即主队列和并行队列。通过
[[NSOperationQueue alloc] init];创建的队列都是并行队列,并且可以将一个或多个NSOperation对象放到队列中去执行,而且是异步执行的,一个NSOperation对象可以通过调用start方法来执行任务,但是默认是同步执行的。则主队列通过
[NSOperationQueue mainQueue];获得,而且其中所有
NSOperation都会在主线程中执行。
当然也可以利用
NSOperationQueue的线程依赖,当某个
NSOperation对象依赖于其它
NSOperation对象的完成时,就可以通过
addDependency方法添加一个或者多个依赖的对象,只有所有依赖的对象都已经完成操作,当前
NSOperation对象才会开始执行操作。需要先添加依赖关系,再将操作添加到队列中。另外,通过
removeDependency方法来删除依赖对象。
dispatch_group_t
可以使用dispatch_group_async函数将多个任务关联到一个
dispatch_group和相应的
queue中,
dispatch_group会并发地同时执行这些任务。而且
dispatch_group可以用来阻塞一个线程,直到
dispatch_group关联的所有的任务完成执行。有时候必须等待任务完成的结果,然后才能继续后面的处理。
多个请求结束后统一操作,最优方案:
假设我们一个页面需要同时进行多个请求,他们之间倒是不要求顺序关系,但是要求等他们都请求完毕了再进行界面刷新或者其他什么操作。
一、dispatch_group_t
image.png
dispatch_group会等和它关联的所有的
dispatch_queue_t上的任务都执行完毕才会发出同步信号,
dispathc_group_notify的代码块block会被执行。从控制台的打印结构可以看出,如果将上面三个操作改成真实的网络操作后,这个简单的做法会变得无效,因为网络请求需要时间,而线程的执行并不会等待请求完成后才真正算作完成,而是只负责将请求发出去,线程就认为自己的任务算完成了,当三个请求都发送出去,就会执行
dispathc_group_notify中的内容,但请求结果返回的时间是不一定的,也就导致界面都刷新了,请求才返回,这就是无效的。
image.png
notify的作用就是在
group中的其他操作全部完成后,再操作自己的内容,所以我们会看到上面事件A、B、C执行之后,才执行事件E。
和
dispatch_async相比,当我们调用
n次
dispatch_group_enter后再调用
n次
dispatch_group_level时,
dispatch_group_notify和
dispatch_group_wait会收到同步信号;这个特点使得它非常适合处理异步任务的同步当异步任务开始前调用
dispatch_group_enter异步任务结束后调用
dispatch_group_leve;
二、dispatch_semaphore_t
image.png
在每个请求开始之前,我们创建一个信号量,初始为0,在请求操作之后,我们设一个
dispatch_semaphore_wait,在请求到结果之后,再将信号量+1,也即是
dispatch_semaphore_signal。这样做的目的是保证在请求结果没有返回之前,一直让线程等待在那里,这样一个线程的任务一直在等待,就不会算作完成,
notify的内容也就不会执行了,直到每个请求的结果都返回了,线程任务才能够结束,这时候
notify也才能够执行。
相关文章推荐
- iOS面试题--网络--如何处理多个网络请求的并发的情况
- iOS在页面销毁时如何优雅的cancel网络请求详解
- iOS如何在页面销毁时优雅的cancel网络请求
- IOS-如何处理多个网络请求的并发的情况
- ios网络学习------5 json格式数据的请求处理
- ios网络学习------8 xml格式数据的请求处理 用代码块封装
- ios网络学习------6 json xml格式数据的请求处理
- (实战)Spring Portlet MVC处理请求分析以及如何快速架构一个Portlet项目
- iOS开发实用技巧篇—项目新特性页面的处理
- iOS面试题 网络请求(一)
- iOS 网络图片处理问题中,怎么解决一个相同的网络地址重复请求的问题
- iOS面试题 网络请求(一)
- 当用Servlet来处理http请求页面时,如何使HTML页面中的
- 数组和字典的writeToFile方法——在项目开发中处理网络数据的时候,可以把请求获得的网络数据保存为plist文件,这样更方便开发
- ios 网络请求总结加强对中文的处理 问题:URL不允许写中文 在GET请求中,相关代码段打断点以验证。
- iOS开发实用技巧—项目新特性页面的处理
- [IOS]UIWebView 请求网络页面或者加载本地资源页面
- 如何使用ListView实现一个带有网络请求,解析,分页,缓存的公共的List页面来大大的提高工作效率
- 如何让php对页面的缓存进行控制 php处理请求的浏览器缓存处理
- iOS开发系列--并行开发(处理多个网络请求并发的情况)