使用GCD的group來控制網絡請求順序

使用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_enterdispatch_group_leave 一般是成對出現的, 進入一次,就得離開一次。也就是說,當離開和進入的次數相同時,就代表任務組完成了。如果enter比leave多,那就是沒完成,如果leave調用的次數多了, 會崩潰的;

dispatch_group_leavedispatch_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這個項目支持下,今年有空會從筆記中整理一些東西出來

文章代碼

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容