轮询请求
最近工作中遇到一个问题,发现用简单的AFNetworking封装,不能满足需求。一般情况下,所有的请求会指定到一个url,然后所有的请求都用AFNetworking的二次封装方法。如自己封装的GET,POST方法.这种封装方式也能满足大多数的需求。
我们的情况稍有不同,请求API实际不多,但是都在一个控制器之内。大概是一个POST和若干个GET,具体场景大概是这个样子。
1、向后台post一个请求,后台会根据情况给我们分配一个服务ID,
2、我们根据该ID,可以使用这个服务。但是服务是有状态限制和生命周期的,create代表服务已经创建,approve代表已经批准,served代表服务过,cancelled代表服务取消。只有在approve的时候我们才能请求后续的API.其他状态下不会有正确的信息返回。
3、在后台分配的服务状态未approve的时候,请求某些API,需要轮询获取服务状态,(因为没有用socket长连接)我们只能自己主动轮询请求。
4、服务状态为approve的时候,可以获取某些实时状态信息,实时信息需要轮询获取,并且有先后顺序。
针对以上要求。我一开始的思路是
网络层用原来的AFNetworking做的简单的二次封装 netManager。然后做下面3中请求
1、netManager 先发送一个post获取到一个服务id
2、netManeger根据服务id,发送get请求,轮询请求,直到服务状态返回的是 approved.才进行下一步的请求。
3、approved的状态下轮询请求实时获取某一个对象的状态信息。直到得到我们想要的状态。
一般情况下,请求1很好完成。
请求2,3用定时器+GCD+runloop可以实现。
但是由于所有的网络请求都有netManager来管理,实际情况下请求1的返回时间比较慢,可能要等8s左右(后台建立服务确实是太耗时了)。
2,3请求用定时器每隔0.5s发一次请求。返回的数据及时在UI上更新。如果网络好的情况下,一般请求没有问题。
但是网络太差的情况下发现由于UI上的动画太过于依赖网络请求,就会发现动画卡主。因为循环请求是同步的,且是在一个线程当中的。就会发现如果有一个请求发生了延迟,后续的就要等待,GCD的同步队列里会有很多个同样的任务(每隔0.5s添加一个)。如果前一个请求a发出的情况下网络阻塞,下一个请求b网络状况又变好了。就会发现后台的服务中我们要的实时信息已经变了,假如后台状态每隔0.5s更新一次,每次+1,最开始是0,因为阻塞我们获取到的信息,第一次是0,第二次就是5了。
所以我们必须在iOS端做超时处理,和POST的超时处理不同,这个超时时间可能是1s左右,因为如果超时时间还和POST设置为8s,一旦网络阻塞,就会发现获取不到实时数据了。
我想的是这样,如果要用一个netManager,肯定不行了。可以这样POST请求单独用一个网络请求类,GET单独用一个网络请求类,分别设置不同的超时时间。
超时之后,由AFNetworking帮我们做错误反馈,我们会在failure回调里发现这个isCancelled的状态。
还有一种方法是用一个定时器,一旦发现超时,主动取消该请求。但是主动取消的接口AFNetworking值给了一个 cancellAll的API.我么的任务是放在一个同步队列里的,所以这中思路似乎不行。如果二次封装可以取消指定的某一个URL下的get请求,但是我们由于是轮询请求,那么每一个请求的URL都一样,会不会把该请求都取消?
有待验证。
建议:就设计两个类网络请求类,除了超时时间设置不一样之外,其他的请求配置都一样。超时时间长的用来做post请求,超时时间短的用来做get请求。