使用GCD的group來控制網絡請求順序
同時發起多個網絡請求,等都完成后,再統一處理
dispatch_group_notify
會等dispatch_group_async
的任務都執行完,再執行
- (void)group1Use
{
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group, queue, ^{
NSLog(@"任務一完成");
});
dispatch_group_async(group, queue, ^{
NSLog(@"任務二完成");
});
dispatch_group_notify(group, queue, ^{
NSLog(@"都完成了");
});
}
如果NSLog(@"任務一完成");
也是異步的,那么就會先輸出“都完成了”,這個更符合實際的網絡請求的場景,dispatch_group_async
中放的是一個網絡請求,我們要的“都完成了”,應該是網絡請求都回調了才輸出"都完成了"
- (void)group2Use
{
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group, queue, ^{
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), queue, ^{
NSLog(@"任務一完成");
});
});
dispatch_group_async(group, queue, ^{
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), queue, ^{
NSLog(@"任務二完成");
});
});
dispatch_group_notify(group, queue, ^{
NSLog(@"都完成了");
});
}
這時候的輸出結果為:
都完成了
任務一完成
任務二完成
顯然這不是我們想要的效果,因此對于這種情況,我們需要用到dispatch_group_enter
,dispatch_group_leave
- (void)group3Use
{
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_group_t group = dispatch_group_create();
dispatch_group_enter(group);
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), queue, ^{
NSLog(@"任務一完成");
dispatch_group_leave(group);
});
dispatch_group_enter(group);
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), queue, ^{
NSLog(@"任務二完成");
dispatch_group_leave(group);
});
dispatch_group_notify(group, queue, ^{
NSLog(@"都完成了");
});
}
這就達到我們的預期了
任務一完成
任務二完成
都完成了
需要注意一點,這里的任務一和任務二不是順序執行的,因為我模擬的都是延遲2s后執行
dispatch_group_enter
和 dispatch_group_leave
一般是成對出現的, 進入一次,就得離開一次。也就是說,當離開和進入的次數相同時,就代表任務組完成了。如果enter比leave多,那就是沒完成,如果leave調用的次數多了, 會崩潰的;
dispatch_group_leave
和dispatch_group_enter
不能在同一個線程,不然會死鎖
其實我們上面的group3Use
的方法就是應用于同時多個發起多個網絡請求,等都完成后,再統一處理
比如:我進入一個app某個頁面,這個頁面要顯示的數據,需要通過5個接口獲取,那么我們就可以用這種方式,同時發起5個請求,等請求都回調完成了,再統一拿數據刷新界面
依次進行網絡請求
介紹一個函數dispatch_group_wait
,這個函數會卡住線程,直到group內的任務執行完。
所以我們可以利用這個函數,來達到依次進行網絡請求
- (void)group4Use
{
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_group_t group = dispatch_group_create();
dispatch_group_enter(group);
// 注意,故意將這個任務一的延遲時間調成4s,比任務二多2s
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(4 * NSEC_PER_SEC)), queue, ^{
NSLog(@"任務一完成");
dispatch_group_leave(group);
});
// 現在group內的任務只有任務一,所以這時候會卡住線程,等任務一執行完畢,這個類似信號量,所以dispatch_group_leave和dispatch_group_enter不能在同一個線程,不然會死鎖
dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
dispatch_group_enter(group);
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), queue, ^{
NSLog(@"任務二完成");
dispatch_group_leave(group);
});
dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
dispatch_group_notify(group, queue, ^{
NSLog(@"都完成了");
});
}
輸出:
任務一完成
任務二完成
都完成了
結語
/ >。< star這個項目支持下,今年有空會從筆記中整理一些東西出來