Для использования результатов поиска в API используется несколько запросов. Он разработан таким образом, потому что поиск может занять много времени (> 5 минут). Первоначальный ответ немедленно возвращается к метаданным о поиске, и эти метаданные используются в последующих запросах до тех пор, пока поиск не будет завершен. Я не контролирую API.Рекурсивные/циклические обработчики завершения асинхронной обработки NSURLSession
- первый запрос является POST к https://api.com/sessions/search/
- Ответ на этот запрос содержит куки и метаданные о поиске. Важными полями в этом ответе являются
search_cookie
(a String) и (a) - 2-й запрос - это POST до https://api.com/sessions/results/ с добавленным к URL-адресу
search_cookie
. например https://api.com/sessions/results/c601eeb7872b7+0 - Ответ на 2 запроса будет содержать либо:
- Результаты поиска, если запрос завершен (он же
search_completed_pct
== 100) - Метаданные о ходе поиска,
search_completed_pct
является прогресс поиск и будет находиться в диапазоне от 0 до 100.
- Результаты поиска, если запрос завершен (он же
- Если поиск не завершен, я хочу, чтобы сделать запрос каждые 5 секунд, пока не будет завершена (иначе
search_completed_pct
== 100)
Я нашел здесь многочисленные сообщения, которые похожи, многие используют группы отправки и для циклов, но этот подход не работает для меня. Я пробовал цикл while и имел проблемы с переменным охватом. Диспетчерские группы также не работали для меня. Это пахло как неправильный путь, но я не уверен.
Я ищу подходящую конструкцию для проведения этих рекурсивных вызовов. Должен ли я использовать делегатов или закрывать + цикл? Я ударил стену и нуждаюсь в некоторой помощи.
Приведенный ниже код не общая идея о том, что я попытался (отредактированный для ясности. Нет dispatch_groups(), обработки ошибок, JSON синтаксического анализа и т.д.)
Viewcontroller.swift
apiObj.sessionSearch(domain) { result in
Log.info!.message("result: \(result)")
})
ApiObj.swift
func sessionSearch(domain: String, sessionCompletion: (result: SearchResult) ->()) {
// Make request to /search/ url
let task = session.dataTaskWithRequest(request) { data, response, error in
let searchCookie = parseCookieFromResponse(data!)
********* pseudo code **************
var progress: Int = 0
var results = SearchResults()
while (progress != 100) {
// Make requests to /results/ until search is complete
self.getResults(searchCookie) { searchResults in
progress = searchResults.search_pct_complete
if (searchResults == 100) {
completion(searchResults)
} else {
sleep(5 seconds)
} //if
} //self.getResults()
} //while
********* pseudo code ************
} //session.dataTaskWithRequest(
task.resume()
}
func getResults(cookie: String, completion: (searchResults: NSDictionary) ->())
let request = buildRequest((domain), url: NSURL(string: ResultsUrl)!)
let session = NSURLSession.sharedSession()
let task = session.dataTaskWithRequest(request) { data, response, error in
let theResults = getJSONFromData(data!)
completion(theResults)
}
task.resume()
}
Это отлично работало, спасибо! Теперь я буду рассматривать Promise как лучший способ реализовать отмену. – Eric
@ Эрик Если вас интересуют _Scala-like_ Фьючерсы и обещания, как показано выше, посмотрите здесь: [Яркие фьючерсы] (https://github.com/Thomvis/BrightFutures) или, как альтернатива [FutureLib] (https : //github.com/couchdeveloper/FutureLib). FutureLib также содержит отдельную независимую библиотеку Cancellation. Эта функция аннулирования полезна для полного скрытия основной задачи, например. ваш клиентский код не нуждается в ссылке на объект «NSURLSessionTask», чтобы иметь возможность отменить запрос. Я автор FutureLib. – CouchDeveloper