Как дождаться ответа одного API и использовать данные для вызова другого API?

Я хочу, чтобы очередь1 завершилась и использовала данные, которые я получаю в CardTheme, и использовала эти данные для вызова второго API. Я хочу использовать group.wait() для достижения этой цели. Но вообще застрял. Кажется, что моя группа находится в основном потоке и вызывает тупик. Я использую пакет Moya для вызова своего API. Как дождаться ответа одного API и использовать данные для вызова другого API?

    let queue1 = DispatchQueue(label: "getBirthdayCardTheme", attributes: .concurrent)
    let queue2 = DispatchQueue(label: "getBirthdayCardDetail", attributes: .concurrent)
    let group = DispatchGroup()

    group.enter()
    queue1.async(group: group){
         InsuranceDataModel.shared.getCardTheme(completionHandler: {
            group.leave()
         },errorHandler:{
            group.leave()
                
         })
    }
    group.wait()
    group.enter()
    queue2.async(group: group){
        InsuranceDataModel.shared.getCardDetail(sender_theme_id: "", pageSize: "1", pageNow: "1", completionHandler: {
             group.leave()
        }, errorHandler: {
             group.leave()
        })
    }

Я редактирую свой код, и это отлично работает для обходного пути. Это странно, что group.wait() не может использовать и вызывает зависание представления.

    let group = DispatchGroup()
    group.enter()
    
    InsuranceDataModel.shared.getCardTheme(completionHandler: {
        //get sender_theme_id here
        group.leave()
    },errorHandler:{
        group.leave()
                
    })
    
    group.notify(.main){
        InsuranceDataModel.shared.getCardDetail(sender_theme_id: "", pageSize: "1", pageNow: "1", completionHandler: {
            
        }, errorHandler: {
        
        })
    }

person frank61003    schedule 27.08.2020    source источник
comment
Не ждите, сообщите. Пожалуйста, научитесь понимать асинхронную обработку данных. В основном запускайте вторую задачу в обработчике завершения первой.   -  person vadian    schedule 27.08.2020
comment
@vadian Я знаю, как ты сказал, и это моя первая мысль. Я хочу знать, как использовать DispatchQueue, чтобы получить тот же эффект и сделать код чище. Спасибо.   -  person frank61003    schedule 28.08.2020
comment
Это другой эффект. Принудительное преобразование асинхронной задачи в синхронную — неэффективная и плохая практика.   -  person vadian    schedule 28.08.2020
comment
@vadian, но мне нужен ответ первого API, чтобы вызвать второй API. Так что все еще нужно дождаться первого завершения API. Я думаю, что это проблема пакета Moya, потому что group.notify может работать нормально.   -  person frank61003    schedule 28.08.2020


Ответы (1)


Вариант 1. Просто добавьте их в одну и ту же очередь, и iOS будет выполнять их один за другим. https://developer.apple.com/documentation/dispatch/dispatchqueue

let queue1 = DispatchQueue(label: "oneQueue") // drop the .concurrent
queue1.async(/* getCardTheme task */)
queue1.async(/* getCardDetail task */)

Вариант 2:

InsuranceDataModel.shared.getCardTheme(completionHandler: {
    InsuranceDataModel.shared.getCardDetail(sender_theme_id: "", pageSize: "1", pageNow: "1", completionHandler: nil, errorHandler: {
                 // handle error?
            })
         },errorHandler:{
            // handle error?
         })
}

EDIT: Вариант 3 — именно то, что вы сделали, просто не используйте очередь .main

    let group = DispatchGroup()
    group.enter()
    
    let queue1 = DispatchQueue(label: "oneQueue") // drop the .concurrent
    queue1.async(execute: {
        debugPrint("Hi I am task 1");
        InsuranceDataModel.shared.getCardTheme(completionHandler: {
          group.leave()
        },errorHandler:{
          group.leave() 
        })
    })
    group.notify(queue: queue1, execute: {
        debugPrint("Hi I am task 2");
        InsuranceDataModel.shared.getCardDetail(/**/)
    })
    debugPrint("All Tasks Submitted")
person Dima G    schedule 27.08.2020
comment
Я знаю, как вы сказали в варианте 2, и это моя первая мысль. Я хочу знать, как использовать DispatchQueue, чтобы получить тот же эффект и сделать код чище. Что вы имеете в виду, что добавить в ту же очередь? API создаст собственную очередь, верно? Спасибо. - person frank61003; 28.08.2020
comment
Привет, братан, я пробую твой отредактированный код. Это не работает. Все еще не могу дождаться ответа первого API для вызова второго API. Очень ценю ваш комментарий. - person frank61003; 03.09.2020
comment
Привет. Еще раз взглянув на ваш вопрос, сложность здесь заключается в том, что ваш метод getCardTheme сам по себе является асинхронным, что означает, что внутри getCardTheme вы запускаете другую асинхронную задачу в некоторой очереди. Я добавил вариант 3, который почти такой же, как и вы, только не в очереди .main - person Dima G; 03.09.2020