問(wèn)題:如何處理異步的網(wǎng)絡(luò)請(qǐng)求?

在開發(fā)中我們常常會(huì)遇到在一個(gè)界面中需要異步請(qǐng)求多個(gè)接口,通過(guò)不同接口的返回?cái)?shù)據(jù)刷新界面不同控件的需求。這種情況下有兩種選擇,一種是 依次請(qǐng)求多個(gè)接口,分別拿到數(shù)據(jù) 這種方式有兩種方法實(shí)現(xiàn):1: 接口回調(diào)嵌套(容易造成代碼金字塔,寫法low)2:管理多線程 使異步的請(qǐng)求操作變成依次執(zhí)行。 依次請(qǐng)求接口的方式很容易造成用戶在當(dāng)前界面請(qǐng)求時(shí)間過(guò)長(zhǎng)而影響體驗(yàn),這就需要我們 并發(fā)的發(fā)起多個(gè)異步請(qǐng)求了,但有時(shí)候我們界面刷新時(shí) 不同界面間的數(shù)據(jù)存在 關(guān)聯(lián),我們得在所有請(qǐng)求完成后才能 統(tǒng)一 對(duì)界面刷新或者其它操作, 下面我簡(jiǎn)單介紹使用GCD 使 監(jiān)聽(tīng)異步請(qǐng)求全部完成 和 異步請(qǐng)求依次進(jìn)行 的方式。

1. 監(jiān)聽(tīng)異步請(qǐng)求全部完成 再完成刷新界面等操作

先上代碼:

 dispatch_group_t group = dispatch_group_create();//創(chuàng)建隊(duì)列組

 dispatch_group_enter(group); //隊(duì)列組中加入一個(gè)異步操作
  //網(wǎng)絡(luò)請(qǐng)求
 [[HttpTool sharedJsonClient]   requestJsonDataWithPath:newUrlString andBlock:^(id  _Nonnull data, NSError * _Nonnull error) {
        NSLog(@"請(qǐng)求第一個(gè)完成");

        //隊(duì)列組中移除一個(gè)異步操作
        dispatch_group_leave(group);
    }];

    dispatch_group_enter(group);
    [[HttpTool sharedJsonClient] requestJsonDataWithPath:newUrlString andBlock:^(id  _Nonnull data, NSError * _Nonnull error) {
        NSLog(@"請(qǐng)求第二個(gè)完成");
        dispatch_group_leave(group);
    }];
    
    dispatch_group_enter(group);
    [[HttpTool sharedJsonClient] requestJsonDataWithPath:newUrlString andBlock:^(id  _Nonnull data, NSError * _Nonnull error) {
        NSLog(@"請(qǐng)求第三個(gè)完成");
        dispatch_group_leave(group);
    }];
    
    
    dispatch_group_notify(group, dispatch_get_main_queue(), ^{
        NSLog(@"請(qǐng)求全部完成 w回到主線程了");
    });

使用了CGD 中隊(duì)列組方式,通過(guò)發(fā)起請(qǐng)求時(shí) 加入一個(gè)異步事件到隊(duì)列組,請(qǐng)求完成后 將其移除, 最終監(jiān)聽(tīng)隊(duì)列組中無(wú)操作時(shí) 即為所有請(qǐng)求事件已完成。 要注意的一點(diǎn)是 網(wǎng)絡(luò)請(qǐng)求本身就是異步的操作, 所以不能寫成:

    dispatch_async(queue, ^{
        [[HttpTool sharedJsonClient] requestJsonDataWithPath:newUrlString andBlock:^(id  _Nonnull data, NSError * _Nonnull error) {
            NSLog(@"請(qǐng)求第一個(gè)完成");
            dispatch_semaphore_signal(semaphore); //信號(hào)量 +1
        }];
    }

2. 使異步的網(wǎng)絡(luò)請(qǐng)求依次進(jìn)行

    //新建一個(gè)串行(并行 都可以)隊(duì)列, 在該 隊(duì)列中對(duì) 所有 的網(wǎng)絡(luò)請(qǐng)求做操作
    dispatch_queue_t queue = dispatch_queue_create("sdsdsdsd", DISPATCH_QUEUE_SERIAL);
    //創(chuàng)建信號(hào)量
    dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); //初始為 0
    NSLog(@"開始執(zhí)行3");
    dispatch_async(queue, ^{

        NSLog(@"開始執(zhí)行1");
        [[HttpTool sharedJsonClient] requestJsonDataWithPath:newUrlString andBlock:^(id  _Nonnull data, NSError * _Nonnull error) {
            NSLog(@"請(qǐng)求第一個(gè)完成");
            dispatch_semaphore_signal(semaphore); //信號(hào)量 +1
        }];
        //信號(hào)量為0 時(shí)不 執(zhí)行  (如果信號(hào)量 不為 0 時(shí)才往下執(zhí)行并且 信號(hào)量 -1)
        dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);

        NSLog(@"開始執(zhí)行2");
        [[HttpTool sharedJsonClient] requestJsonDataWithPath:newUrlString andBlock:^(id  _Nonnull data, NSError * _Nonnull error) {
            NSLog(@"請(qǐng)求第二個(gè)完成");
            dispatch_semaphore_signal(semaphore); //信號(hào)量 +1
        }];
        //信號(hào)量為0 時(shí)不 執(zhí)行  (如果信號(hào)量 不為 0 時(shí)才往下執(zhí)行并且 信號(hào)量 -1)
        dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);


        NSLog(@"開始執(zhí)行3");
        [[HttpTool sharedJsonClient] requestJsonDataWithPath:newUrlString andBlock:^(id  _Nonnull data, NSError * _Nonnull error) {
            NSLog(@"請(qǐng)求第三個(gè)完成");
            dispatch_async(queue, ^{
                 dispatch_semaphore_signal(semaphore); //信號(hào)量 +1
            });

        }];

        //信號(hào)量為0 時(shí)不 執(zhí)行  (如果信號(hào)量 不為 0 時(shí)才往下執(zhí)行并且 信號(hào)量 -1)
        dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
        NSLog(@"在當(dāng)前線程中繼續(xù)執(zhí)行");
    });

需要注意的事項(xiàng)是:

  • 如果在 主隊(duì)列中 做 信號(hào)量的加減和wait等操作 ,dispatch_semaphore_wait 方式會(huì)阻塞當(dāng)前線程(主線程),而網(wǎng)絡(luò)請(qǐng)求的回調(diào)默認(rèn)是回到主線程中 處理事件的, 由此會(huì)導(dǎo)致 主線程中 dispatch_semaphore_signal(semaphore); 方法不會(huì)執(zhí)行,造成主線程死鎖。 所以,只能新建一個(gè) 串行或者 并行 隊(duì)列(新建隊(duì)列的時(shí)候會(huì)開一條線程管理事件) 對(duì) 網(wǎng)絡(luò)請(qǐng)求操作 做管理 (不能在主隊(duì)列)
  • 使用AFN網(wǎng)絡(luò)請(qǐng)求操作會(huì)自動(dòng)開啟子線程執(zhí)行,而請(qǐng)求完成后的操作會(huì)自動(dòng)回到主線程。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容