iOS 网络请求依赖关系

以下是我的拙见,如有不当之处,欢迎大家指正!

一、在上一个网络请求的完成回调中调用写一个网络请求

这是一个最普通的思路,在上一个请求完成的回调中进行下一次的请求

二、利用NSOperation添加依赖操作和优先级

这个方法主要利用NSOperationaddDependency:方法来添加依赖

    /// 操作(模拟网络请求)
    NSBlockOperation *operation1 = [NSBlockOperation blockOperationWithBlock:^{
        [self network_request1];
    }];
    
    NSBlockOperation *operation2 = [NSBlockOperation blockOperationWithBlock:^{
        [self network_request2];
    }];
    
    NSBlockOperation *operation3 = [NSBlockOperation blockOperationWithBlock:^{
        [self network_request3];
    }];

    /// 添加依赖
    [operation2 addDependency:operation1];
    [operation3 addDependency:operation2];
    
    /// 创建队列
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
    [queue addOperations:@[operation1, operation2, operation3] waitUntilFinished:NO];

模拟网络请求

#pragma mark - Network
- (void)network_request1 {
    sleep(3);
    NSLog(@"-------- network request 1");
}

- (void)network_request2 {
    sleep(2);
    NSLog(@"-------- network request 2");
}

- (void)network_request3 {
    sleep(1);
    NSLog(@"-------- network request 3");
}

三、Dispatch_group 组队列

这个思路主要用到的方法有dispatch_group_enterdispatch_group_leavedispatch_group_waitdispatch_group_notify
在请求之前进入group:“dispatch_group_enter
在请求之后离开group:“dispatch_group_leave
group 内的任务为当前任务,所以这时候会卡住线程,等任务一执行完毕,这个类似信号量“dispatch_group_wait
注意:dispatch_group_enter 和dispatch_group_leave 成对出现,且在真实的网络请求环境中,请求成功或者失败都要leave

/// 创建组队列
    self.group = dispatch_group_create();
    /// 模拟网络请求
    [self network_request1];
    [self network_request2];
    [self network_request3];
    
    /// group 中任务全部完成
    dispatch_group_notify(self.group, dispatch_get_main_queue(), ^{
        NSLog(@"请求完成");
    });

模拟网络请求

#pragma mark - Network
- (void)network_request1 {
    /// 任务开始之前进入group
    dispatch_group_enter(self.group);
    sleep(3);
    NSLog(@"-------- network request 1");
    /// 任务完成,离开group,与 enter成对出现
    dispatch_group_leave(self.group);
    /// 现在 group 内的任务为当前任务,所以这时候会卡住线程,等任务一执行完毕,这个类似信号量
    /// 注意 dispatch_group_leave 和 dispatch_group_enter 不能在同一个线程,不然会死锁
    dispatch_group_wait(self.group, DISPATCH_TIME_FOREVER);
}

- (void)network_request2 {
    /// 任务开始之前进入group
    dispatch_group_enter(self.group);
    sleep(2);
    NSLog(@"-------- network request 2");
    /// 任务完成,离开group,与 enter成对出现
    dispatch_group_leave(self.group);
    
    dispatch_group_wait(self.group, DISPATCH_TIME_FOREVER);
}

- (void)network_request3 {
    /// 任务开始之前进入group
    dispatch_group_enter(self.group);
    sleep(1);
    NSLog(@"-------- network request 3");
    /// 任务完成,离开group,与 enter成对出现
    dispatch_group_leave(self.group);
    
    dispatch_group_wait(self.group, DISPATCH_TIME_FOREVER);
}

四、Dispatch_barrier 任务阻塞

主要方法dispatch_barrier_syncdispatch_barrier_async
相同点:都会等待方法之前的任务执行完,再执行方法后的任务
不同点:dispatch_barrier_sync会等待自己的block中任务执行完在执行方法之后的任务,而dispatch_barrier_async不会等待自己的任务结束,会继续执行后面的任务

/// 创建线程
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
        
    dispatch_sync(queue, ^{
        [self network_request1];
    });
    /// 阻塞当前线程
    dispatch_barrier_sync(queue, ^{
        NSLog(@"第一个请求完成");
    });
    
    dispatch_sync(queue, ^{
        [self network_request2];
    });
    dispatch_barrier_sync(queue, ^{
        NSLog(@"第二个请求完成");
    });
    
    dispatch_sync(queue, ^{
        [self network_request3];
    });
    dispatch_barrier_sync(queue, ^{
        NSLog(@"第三个请求完成");
    });

模拟网络请求

#pragma mark - Network
- (void)network_request1 {
    sleep(3);
    NSLog(@"-------- network request 1");
}

- (void)network_request2 {
    sleep(2);
    NSLog(@"-------- network request 2");
}

- (void)network_request3 {
    sleep(1);
    NSLog(@"-------- network request 3");
}

五、Dispatch_semaphore 信号量

主要方法:dispatch_semaphore_signaldispatch_semaphore_wait
当信号量为0则该函数就会一直等待,也就是不返回(相当于阻塞当前线程),dispatch_semaphore_signal我理解为订阅信号,会使得信号量+1dispatch_semaphore_wait会使信号量-1。当信号量不大于0时,信号量-1,同时后续代码会继续执行,但是当信号量等于0时,信号量不做减1动作,同时阻塞当前的执行,在timeout之前遇到信号量大于0时,会继续做-1操作,并执行后续任务。

/// 信号量 为 0,则该函数就会一直等待,也就是不返回(相当于阻塞当前线程)
    dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
    /// 创建线程
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    
    dispatch_async(queue, ^{
        [self network_request1];
        /// 请求完成订阅信号
        dispatch_semaphore_signal(semaphore);
    });
    /// 等待信号
    dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
    
    dispatch_async(queue, ^{
        [self network_request2];
        dispatch_semaphore_signal(semaphore);
    });
    dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
    
    dispatch_async(queue, ^{
        [self network_request3];
        dispatch_semaphore_signal(semaphore);
    });
    dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);

模拟网络请求

#pragma mark - Network
- (void)network_request1 {
    sleep(4);
    NSLog(@"-------- network request 1");
}

- (void)network_request2 {
    sleep(2);
    NSLog(@"-------- network request 2");
}

- (void)network_request3 {
//    sleep(1);
    NSLog(@"-------- network request 3");
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容