一個頁面中有多個網絡請求時,怎麼寫比較合理?

1、2個請求沒有依賴性,可是要求2個請求都完成後才能刷新UI。ios

2、2個請求有依賴性,A請求完成後,B請求須要用到 A 返回的結果  做爲參數進行請求。api

 

先解決第一個:網絡

使用GCD的 group ,等兩個請求都完成後,在刷新UI.代碼以下:異步

- (void)request{
    
//建立一個GCD group
    self.group = dispatch_group_create();
    
//將請求放入group中處理
    dispatch_group_async(self.group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        [self request1];
    });
    
    dispatch_group_async(self.group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        [self request2];
    });
    
    dispatch_group_async(self.group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        [self request3];
    });
    
//監聽group中任務是否都完成了,完成了就執行刷新界面
    dispatch_group_notify(self.group, dispatch_get_main_queue(), ^{
        NSLog(@"刷新界面");
    });
}
//請求1
-(void)request1{
    
    AFHTTPSessionManager *manger = [AFHTTPSessionManager manager];
    NSString *url = @"http://v3.wufazhuce.com:8000/api/channel/movie/more/0?platform=ios&version=v4.0.1";
    [manger GET:url parameters:nil progress:^(NSProgress * _Nonnull downloadProgress) {
        
    } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        NSArray *data = responseObject[@"data"];
        for (NSDictionary *dic in data) {
            NSLog(@"請求1---%@",dic[@"id"]);
        }
        

    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {

    }];
}



//請求2
-(void)request2{
    
    AFHTTPSessionManager *manger = [AFHTTPSessionManager manager];
    NSString *url = @"http://v3.wufazhuce.com:8000/api/channel/movie/more/0?platform=ios&version=v4.0.1";
    [manger GET:url parameters:nil progress:^(NSProgress * _Nonnull downloadProgress) {
        
    } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        NSArray *data = responseObject[@"data"];
        for (NSDictionary *dic in data) {
            NSLog(@"請求2---%@",dic[@"id"]);
        }
        

    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        

    }];
}



//請求3
-(void)request3{
    
    AFHTTPSessionManager *manger = [AFHTTPSessionManager manager];
    NSString *url = @"http://v3.wufazhuce.com:8000/api/channel/movie/more/0?platform=ios&version=v4.0.1";
    [manger GET:url parameters:nil progress:^(NSProgress * _Nonnull downloadProgress) {
        
    } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        NSArray *data = responseObject[@"data"];
        for (NSDictionary *dic in data) {
            NSLog(@"請求3---%@",dic[@"id"]);
        }
        

    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        

    }];
}

運行結果:async

我擦,說好的先執行group中的任務,等group中的任務都執行完成後,再執行刷新UI的呢?事與願違啊!url

通過查證找出了緣由,緣由就是:咱們的網絡請求AFN發送請求也是在異步線程的。上面這種將請求放入group的寫法遵照的整組所有執行完畢指的是三個block寫的代碼直觀進行執行完,就算執行完畢。也就是說[self request1] 執行AFN的代碼完了,不包含AFN異步請求。  所以會出現這樣的結果。spa

 

改正:線程

網上有不少人用group 和 信號量來解決這個問題,其實不須要信號量,隊列組就能解決了。只要換一種方式將任務加入隊列組就好了。code

- (void)request{
    
    self.group = dispatch_group_create();
    
    //下面的任務立刻要放到group中執行了
    dispatch_group_enter(self.group);
    [self request1];
    
    
    //下面的任務立刻要放到group中執行了
    dispatch_group_enter(self.group);
    [self request2];
    
    
    //下面的任務立刻要放到group中執行了
    dispatch_group_enter(self.group);
    [self request3];
    
    
    dispatch_group_notify(self.group, dispatch_get_main_queue(), ^{
        NSLog(@"刷新界面");
    });
}
-(void)request1{
    
    
    AFHTTPSessionManager *manger = [AFHTTPSessionManager manager];
    NSString *url = @"http://v3.wufazhuce.com:8000/api/channel/movie/more/0?platform=ios&version=v4.0.1";
    [manger GET:url parameters:nil progress:^(NSProgress * _Nonnull downloadProgress) {
        
    } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        NSArray *data = responseObject[@"data"];
        for (NSDictionary *dic in data) {
            NSLog(@"請求1---%@",dic[@"id"]);
        }
        //任務完成了,該任務從group中移除
        dispatch_group_leave(self.group);
        
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        
        //任務完成了,該任務從group中移除
        dispatch_group_leave(self.group);
    }];
}




-(void)request2{
    
   
    AFHTTPSessionManager *manger = [AFHTTPSessionManager manager];
    NSString *url = @"http://v3.wufazhuce.com:8000/api/channel/movie/more/0?platform=ios&version=v4.0.1";
    [manger GET:url parameters:nil progress:^(NSProgress * _Nonnull downloadProgress) {
        
    } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        NSArray *data = responseObject[@"data"];
        for (NSDictionary *dic in data) {
            NSLog(@"請求2---%@",dic[@"id"]);
        }
        //任務完成了,該任務從group中移除
        dispatch_group_leave(self.group);
        
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        
        //任務完成了,該任務從group中移除
        dispatch_group_leave(self.group);
    }];
}



-(void)request3{
    
    
    AFHTTPSessionManager *manger = [AFHTTPSessionManager manager];
    NSString *url = @"http://v3.wufazhuce.com:8000/api/channel/movie/more/0?platform=ios&version=v4.0.1";
    [manger GET:url parameters:nil progress:^(NSProgress * _Nonnull downloadProgress) {
        
    } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        NSArray *data = responseObject[@"data"];
        for (NSDictionary *dic in data) {
            NSLog(@"請求3---%@",dic[@"id"]);
        }
        
        //任務完成了,該任務從group中移除
        dispatch_group_leave(self.group);
        
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        
        //任務完成了,該任務從group中移除
        dispatch_group_leave(self.group);
    }];
}

這種dispatch_group_enterdispatch_group_leave是成對出現的,當進入一個操做後,在適當的位置加上dispatch_group_leave,好比在這裏,進入第一個 enter 執行 request1 操做,那麼在這個方法中異步返回的時候(成功或失敗)寫上 dispatch_gropu_leave,這樣就包含了異步的狀況。orm

 

 

2、解決有依賴的兩個請求

// 建立一個隊列
    NSOperationQueue *queue = [[NSOperationQueue alloc]init];
    
    
    // 建立一個A操做
    NSBlockOperation *operationA = [NSBlockOperation blockOperationWithBlock:^{

        
        [self requestA];
    }];
    
    
    
    // 建立一個B操做
    NSBlockOperation *operationB = [NSBlockOperation blockOperationWithBlock:^{

        [self requestB];
        
    }];
    
    
    //添加依賴 B要在A打印完在進行打印 因此是B依賴於A 那麼只須要添加以下代碼便可完成
    [operationB addDependency:operationA];
    
    
    // 分別加入到隊列中
    [queue addOperation:operationA];
    [queue addOperation:operationB];
-(void)requestA{
    
    
    AFHTTPSessionManager *manger = [AFHTTPSessionManager manager];
    NSString *url = @"http://v3.wufazhuce.com:8000/api/channel/movie/more/0?platform=ios&version=v4.0.1";
    [manger GET:url parameters:nil progress:^(NSProgress * _Nonnull downloadProgress) {
        
    } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        NSArray *data = responseObject[@"data"];
        for (NSDictionary *dic in data) {
            NSLog(@"請求AAA---%@",dic[@"id"]);
        }
        
        
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        
    }];
}


-(void)requestB{
    
    
    AFHTTPSessionManager *manger = [AFHTTPSessionManager manager];
    NSString *url = @"http://v3.wufazhuce.com:8000/api/channel/movie/more/0?platform=ios&version=v4.0.1";
    [manger GET:url parameters:nil progress:^(NSProgress * _Nonnull downloadProgress) {
        
    } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        NSArray *data = responseObject[@"data"];
        for (NSDictionary *dic in data) {
            NSLog(@"請求BBB---%@",dic[@"id"]);
        }
        
        
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        
    }];
}

這裏我沒有在一個線程請求返回成功後,再發起第二個請求,這種方式也能解決問題,可是這樣寫代碼會比較亂,我不喜歡這麼寫。

相關文章
相關標籤/搜索