大量嵌套完成块的替代品?

问题描述 投票:0回答:2

我正在使用 OAuthSwift 访问 goodreads API。首先,我有一个 API 调用来获取用户 ID。然后,使用该 ID,我获取用户书架上的书籍。然后我检查是否有任何具有特定标题的书籍,如果没有,我会再次调用 API 来创建该书。然后,在确保这本书在那里的情况下,我会发布有关其进度的状态更新。

这是获取用户id的代码:

    oAuth.client.get(
        "https://www.goodreads.com/api/auth_user",
        success: {
            data, response in
            // Here I use the returned ID to get the books.
        },
        failure: {
            error in
            //…
        }
    )

获得 ID 后,我需要将其用于下一次获取书籍的 API 调用。问题是,我不能只在第一个调用之后添加下一个调用,因为它们是异步的,因此第二个调用将在我从第一个调用获得 ID 之前开始。

那么,我正在做的就是在

success

 闭包中添加第二个 API 调用(我在代码中用注释指出了这一点)。所以我有两段非常相似的代码,一个在另一个里面;当第一个 API 调用成功时,它会调用下一个。但随后我必须使用第二次调用的结果来决定是否添加新书。因此,我在第二次调用的成功块内进行了第三次 API 调用(用于添加书籍),该调用位于第一个调用的成功块内……您可以看到事情开始变得非常混乱。它甚至还不止于此:我有第四个 API 调用来发布状态更新,它位于第三个调用的完成处理程序内,第三个调用位于第二个调用的完成处理程序内,第三个调用位于第一个调用的完成处理程序内。

那么……我应该做什么呢?如果这是一个愚蠢的问题,我很抱歉,但我在 swift 和整体编程方面都是新手。

ios swift asynchronous oauth
2个回答
-1
投票

我认为Apple已经提供了使用GCD处理这种情况的最佳方法,GCD提供串行队列以串行方式执行块/API。这是先进先出顺序

let serialQueue : dispatch_queue_t = dispatch_queue_create("com.yourSerialQueue.queue", DISPATCH_QUEUE_SERIAL); dispatch_async(serialQueue) { () -> Void in //Call First API print("First API call succeed") }; dispatch_async(serialQueue) { () -> Void in //Call Second API print("Second API call succeed") }; dispatch_async(serialQueue) { () -> Void in //Call Third API print("Third API call succeed") }; dispatch_async(serialQueue) { () -> Void in //Call Fourth API print("Fourth API call succeed") };

输出:

First API call succeed Second API call succeed Third API call succeed Fourth API call succeed
    

-2
投票
我对 GCD 还没有深入的了解,对于你的场景,我可以建议你真正快速地调用每个 API,如下所示的完成块,(这是我现在可以帮助你的)

dispatch_queue_t backgroundQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); dispatch_async(backgroundQueue, ^{ [self callGetUserIdAPIAndCompletion:^(NSDictionary *dictResponse) { [self callGetBooksAPIForUserId:dictResponse[@"userId"] AndCompletion:^(NSDictionary *dictResponse) { [self callAddBookAPIForUserId:dictResponse[@"userId"] bookId:dictResponse[@"bookId"] AndCompletion:^(NSDictionary *dictResponse) { [self callPostStatusUpdateAPIForUserId:dictResponse[@"userId"] status:@"status" AndCompletion:^(NSDictionary *dictResponse) { }]; }]; }]; }]; });

并编写您的API调用函数如下

-(void)callGetUserIdAPIAndCompletion:(void(^)(NSDictionary *dictResponse))completion { NSDictionary *dictResponse; //Call First API NSLog(@"API 1 completes"); completion(dictResponse); } -(void)callGetBooksAPIForUserId:(NSString*)userId AndCompletion:(void(^)(NSDictionary *dictResponse))completion { NSDictionary *dictResponse; //Call Second API with userId NSLog(@"API 2 completes"); completion(dictResponse); } -(void)callAddBookAPIForUserId:(NSString*)userId bookId:(NSString*)bookId AndCompletion:(void(^)(NSDictionary *dictResponse))completion { NSDictionary *dictResponse; //Call Third API with userId and bookId NSLog(@"API 3 completes"); completion(dictResponse); } -(void)callPostStatusUpdateAPIForUserId:(NSString*) userId status:(NSString*) status AndCompletion:(void(^)(NSDictionary *dictResponse))completion { NSDictionary *dictResponse; //Call Fourth API with userId and status NSLog(@"API 4 completes"); completion(dictResponse); }
    
© www.soinside.com 2019 - 2024. All rights reserved.