Using dispatch groups to wait for multiple web services
来源:互联网 发布:康耐视视觉检测软件 编辑:程序博客网 时间:2024/05/21 05:55
Imagine your app has to run a series of nice web service calls. These could be for a set-up task, for example - when your app launches it may need to get various bits of configuration information from a server. This could involve hitting several endpoints.
You want to call a single method to kick this process off, and have a completion block run when it has finished. The web services don’t depend on each other. How can this be done?
There’s a horrible way: start each service from the completion block of the previous one, and when the last one is done, call your overall completion block.
Any time you see this in your code, you’re probably doing it wrong:
}]; }]; }]; }]; }];
The nice way to do this is by using dispatch groups. A dispatch group monitors work that has been added to it, and it will know when that work is done.
Creating a dispatch group
This is easy:
dispatch_group_t serviceGroup = dispatch_group_create();
Adding tasks to a dispatch group
There are two ways to do this. The first adds a block of code to the group, to be executed on a specfied queue:
dispatch_group_async(serviceGroup,queue,^{ // some work here});
This isn’t really suitable for us; our web service calls return straight away and have their own completion blocks, so the group would think the work was done immediately.
The second way is to manually tell the group that you are starting, or have finished, blocks of work. This is done using dispatch_group_enter() and dispatch_group_leave() respectively:
dispatch_group_enter(serviceGroup);[configService startWithCompletion:^(ConfigResponse *results, NSError* error){ // Do something with the error or results dispatch_group_leave(serviceGroup);}];
Each enter must be balanced by a corresponding leave, or the group will never finish. You enter before calling the service, and leave at the end of the completion block.
Acting when the group is finished
There are two options here as well. You can block the current thread until the group is finished:
dispatch_group_wait(serviceGroup,DISPATCH_TIME_FOREVER);
// Won’t get here until everything has finished
Or, you can tell the group to run another block when the work is done, and then return from your method:
dispatch_group_notify(serviceGroup,dispatch_get_main_queue(),^{ // Won't get here until everything has finished });
The latter seems more suited to our purposes - we expect methods with completion blocks to return immediately.
Putting it all together
We can implement our multiple-web-service-calling method like this:
-(void)fetchConfigurationWithCompletion:(void (^)(NSError* error))completion { // Define errors to be processed when everything is complete. // One error per service; in this example we'll have two __block NSError *configError = nil; __block NSError *preferenceError = nil; // Create the dispatch group dispatch_group_t serviceGroup = dispatch_group_create(); // Start the first service dispatch_group_enter(serviceGroup); [self.configService startWithCompletion:^(ConfigResponse *results, NSError* error){ // Do something with the results configError = error; dispatch_group_leave(serviceGroup); }]; // Start the second service dispatch_group_enter(serviceGroup); [self.preferenceService startWithCompletion:^(PreferenceResponse *results, NSError* error){ // Do something with the results preferenceError = error; dispatch_group_leave(serviceGroup); }]; dispatch_group_notify(serviceGroup,dispatch_get_main_queue(),^{ // Assess any errors NSError *overallError = nil; if (configError || preferenceError) { // Either make a new error or assign one of them to the overall error overallError = configError ?: preferenceError; } // Now call the final completion block completion(overallError); }); }
You keep track of any errors encountered by the individual service and can either make a new NSError object based on what went wrong, or pick a particular one to return.
This is far superior to chaining calls via their completion blocks - particularly if you decide to remove a call, or add extra ones.
repost from http://commandshift.co.uk/blog/2014/03/19/using-dispatch-groups-to-wait-for-multiple-web-services/
- Using dispatch groups to wait for multiple web services
- 使用Dispatch Groups来管理多个Web Services请求
- Using gsoap for web services
- [IOS/翻译]GCD-3 Using Dispatch Groups
- Using gsoap for web services in symbian
- Using Web Services for Remoting over the Internet.
- Using Web Services for Remoting over the Internet.
- 4 Steps to Consume Web Services using Ajax
- Using SharePoint Web Services to Fill Out an InfoPath Form
- How to write RESTful web services using spring 3 mvc
- Using Web Services Effectively
- Using Windows Web Services
- Using a Java class to control directory searches for people and groups
- Web services for RoR
- Schema for Web Services
- Introduction to Web Services
- How To Configure Client Failover For Dataguard Connections Using Database Services (Doc ID 1429223.1
- 《Packt.Mastering.Go.Web.Services.2015.4.pdf》之Using Gorilla for JSON-RPC
- OpenCV从入门到放弃(四):HighGui组件细讲
- Android平台遥控器按键映射流程
- 欢迎使用CSDN-markdown编辑器
- Mac OS X 系统12个常用的文本编辑快捷键(移动、选中)
- 莫斯科大学数学力学系 数学部专门化课程目录
- Using dispatch groups to wait for multiple web services
- MongoDB下载和安装
- LINUX 驱动学习 -设备模型之别人的理解(2)
- MyBatis_3.4.0学习系列(一)
- Djang建立项目
- 编译原理之词法分析和语法分析
- mySql实用小常识
- 自定义控件三部曲之绘图篇(十七)——为Bitmap添加阴影并封装控件
- spark学习 —— 入门