AFNetworing同步网络请求?

今天遇到了一个有关同步网络请求的需求是这样的,App中所有网络请求都需要使用一个BaseUrl作为前缀,这个前缀需要一个专门的配置接口去请求获取。考虑到如果在App启动的时候异步请求配置接口获取BaseUrl,并不能保证APP首页发起的网络请求前缀是正确的BaseUrl,于是我考虑采用同步请求的方法确保BaseUrl的获取。

因为我们在开发App的时候常用的网络框架就是AFNetWorking ,于是我首先想到了使用AFNetworking结合信号量的方式来实现这个同步请求,代码如下:

//更新系统配置,获取BaseUrl的方法,在App启动时候调用
- (void)updateAppSystemConfig{
    //1.创建信号量,阻塞了主线程
    dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        //这里省略了AFN请求网络的方法,成功和失败的回调里都需要调用下面的代码
        //2.网络请求结束,发送通知信号
        //dispatch_semaphore_signal(semaphore);
    });
    // 3.发送等待信号
    dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
    //同步请求配置结束之后,结束阻塞
}

但是上述的代码却无形中造成了死锁的问题。这是因为我们使用GCD的信号量首先阻塞了主线程,而是在异步线程里使用了AFN请求网络,由于AFN自身的原因,无论还是成功还是失败网络请求的响应总是要回到主线程中进行操作,但是此时的主线程却是阻塞的,所以就互相等待就造成了死锁。

然后我就采用了系统自带的网络请求的方法来解决这个问题,代码如下:

//更新系统配置,获取BaseUrl的方法,在App启动时候调用
- (void)updateAppSystemConfig{
    //1.创建信号量
    dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        //开始异步请求操作
        NSURL*url=[NSURL URLWithString:Path_app_config];
        //创建请求命令,并设置缓存策略
        NSURLRequest *request= [NSURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:15];
        //创建会话对象通过单例方法实现
        NSURLSession *session=[NSURLSession sharedSession];
        //执行会话的任务
        NSURLSessionTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
            if (error) {
                NSLog(@"请求配置失败了");
            }else{
                NSDictionary *responData=[NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:&error];
                if ([responData[@"errcode"] integerValue] ==QQMFRequest_OK) {
                    //网络请求成功,将新配置更新到本地,可以从配置数据中得到BaseUrl
                    [AppConfigTools updateAppConfigWithData:responData];
                }
            }
            // 2.在网络请求结束后发送通知信号
            dispatch_semaphore_signal(semaphore);
        }];
        //开始执行任务
        [task resume];
    });
    // 3.发送等待信号
    dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
    //同步请求配置结束之后,结束阻塞
}

这里使用的是系统自带的网络请求,请求系统配置BaseUrl的网络请求是在异步线程里实现的,而且网络请求完成之后发出信号量的通知也是在异步线程中,这样就不会造成了阻塞。也实现了同步等待的需求。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏未闻Code

TeamFlowy——结合Teambition与Workflowy

Teambition是一个跨平台的团队协作和项目管理工具,相当于国外的Trello。使用Teambition可以像使用白板与便签纸一样来管理项目进度,如下图所示...

1771
来自专栏锦小年的博客

Linux使用笔记2-screen的妙用(保留端口会话)

现在一般都是用Windows通过ssh连接到linux,有时候工作到兴起,断网了、或者重启了,这时候一切都完了,重新连接也不能回到以前的会话。那么有没有一种可能...

1928
来自专栏哈雷彗星撞地球

Xcode 创建.a和framework静态库

最近因为项目中的聊天SDK,需要封装成静态库,所以实践了一下创建静态库的步骤,做下记录。

2112
来自专栏北京马哥教育

解决Redis 延迟故障

症状 前一段时间redis客户端在使用php connect 连接redis 的经常报一个redis server went away 等信息。 排查 首先想到...

3468
来自专栏公有云大数据平台弹性 MapReduce

Redis 单机主从高可用性优化

redis是一款高性能的内存数据库,本文侧重描述redis在主从模式下遇到的一些问题以及如何调优,特别是在云环境下遇到的一些特殊问题,至于redis如何使用以及...

4.8K0
来自专栏未闻Code

TeamFlowy——结合Teambition与Workflowy

Teambition是一个跨平台的团队协作和项目管理工具,相当于国外的Trello。使用Teambition可以像使用白板与便签纸一样来管理项目进度,如下图所示...

1533
来自专栏一“技”之长

iOS网络编程之六——数据缓存类NSURLCache使用解析

        在前面博客中,介绍了NSURLRequest请求类的相关使用方法,其中有介绍关于请求返回数据的缓存策略,实际上,iOS中具体缓存操作的管理是由N...

802
来自专栏Java编程技术

使用MySQL Server Side Cursor解决查询数据量过大造成OOM

前面介绍了MyBaits中两种使用游标的方式来避免搜查内容过大导致OOM,这两种方式被称为是客户端side的游标,因为mysql client每次从自己的接受b...

1361
来自专栏跟着阿笨一起玩NET

Log4Net日志记录两种方式

     log4net库是Apache log4j框架在Microsoft .NET平台的实现,是一个帮助程序员将日志信息输出到各种目标(控制台、文件、数据库...

3692
来自专栏梦里茶室

【Chromium中文文档】Chromium如何展示网页

这个文档从底层描述了Chromium是如何展示网页的。请确认你已经读过多进程架构这篇文章。你会特别想要了解主要组件的框架。你也可能对多进程资源加载感兴趣,以了解...

2405

扫码关注云+社区

领取腾讯云代金券