许多嵌套完成块的替代方案?

时间:2016-02-26 04:50:59

标签: ios swift api asynchronous oauth

我正在使用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调用,它可以获取书籍。问题是,我不能在第一个之后添加下一个调用,因为它们是异步的,所以第二个调用将在我从第一个调用之前开始。

我正在做的是在success闭包内添加第二个api调用(我在代码中用注释指出)。所以我在另一个内部有两个非常相似的代码片段;当第一个api调用成功时,它会调用下一个。但是我必须使用第二次调用的结果来决定是否要添加新书。所以我在第二次调用的成功块内有第三次api调用(添加本书),这是第一次调用的成功块内...你可以看到事情开始变得非常混乱。它甚至没有停在那里:我有第四次api调用来发布状态更新,它在第三次调用的完成处理程序内,在第二次调用的内部,在第一次调用的内部。

那么......我该怎么做呢?如果这是一个愚蠢的问题,我很抱歉,但是我很快就会擅长整体编程。

2 个答案:

答案 0 :(得分:-1)

我认为Apple提供了使用GCD处理此场景的最佳方法,GCD提供串行队列以串行方式执行块/ API。这是FIFO顺序

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

答案 1 :(得分:-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);
}