2016-02-26 3 views
1

Я использую OAuthSwift для доступа к goodreads api. Сначала у меня есть api-вызов, чтобы получить идентификатор пользователя. Затем, используя этот идентификатор, я получаю книги, которые пользователь имеет на полке. Затем я проверяю, есть ли книги с определенным заголовком, а если нет, я снова вызываю api, чтобы создать эту книгу. И затем, будучи уверенным, что книга есть, я публикую обновление статуса о его прогрессе.Альтернативы множеству вложенных блоков завершения?

Это код, чтобы получить идентификатор пользователя:

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 
      //… 
     } 
    ) 

После того, как я получил идентификатор, мне нужно, чтобы использовать его для следующего апи вызова, который получает книгу. Дело в том, что я не могу просто добавить следующий вызов после первого, потому что они асинхронны, поэтому второй вызов начнется, прежде чем я получу идентификатор из первого.

То, что я делаю, заключается в том, чтобы добавить второй вызов api внутри этого success закрытия (я указал его в коде с комментарием). Итак, у меня есть два очень похожих фрагмента кода один внутри другого; когда первый вызов api преуспевает, он вызывает следующее. Но тогда я должен использовать результат этого второго вызова, чтобы решить, добавлю ли я новую книгу или нет. Поэтому у меня есть третий вызов api (чтобы добавить книгу) внутри блока успеха второго вызова, который находится внутри блока успеха первого вызова ... и вы можете видеть, что все начинает становиться довольно запутанным. И он даже не останавливается на достигнутом: у меня есть четвертый вызов api для публикации обновления состояния, и он находится внутри обработчика завершения третьего вызова, который находится внутри второго, который находится внутри первого.

Итак ... что я должен делать вместо этого? Извините, если это глупый вопрос, но я новичок в быстром и программировании в целом.

+2

Вы можете использовать PromiseKit http://promisekit.org – Paulw11

+0

Вы можете обернуть вызовы в 'NSOperations' и поместить их в последовательный' NSOperationQueue' – dan

+0

@Paul Ничего себе, это выглядит многообещающе. (Посмотри, что я там сделал?) Я посмотрю, спасибо! – dbmrq

ответ

-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 
+0

Если вызов представляет собой метод асинхронизации, такой как сетевой вызов, таким образом вы связываете только начало запросов, а не ответ – Andrea

-2

не имеют глубокие знания НОД еще, для сценария, что я могу предложить вам в режиме реального времени быстро, это позвонить каждый 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); 
} 
+0

Здравствуйте. Вопрос помечен как «быстрый», пожалуйста, укажите ответ в Swift, а не на другом языке. Благодаря! – Moritz

Смежные вопросы