Создание простого экрана поиска с помощью «DispatchWorkItem» и «DispatchGroup» для выполнения нескольких вызовов асинхронной службы к нескольким источникам.

Вы можете найти версию этого сообщения для Combine Framework здесь

Https://medium.com/better-programming/how-to-query-multiple-apis-with-the-combine-framework-1c4e0298418e

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

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

В этом случае вы просто запускаете задачу с задержкой. Если событие продолжается, вы отменяете предыдущую задачу и запускаете новую.

Автозаполнение - хороший пример такого рода ситуаций. Каждый раз, когда вы нажимаете клавишу, функция автозаполнения предлагает вам несколько вариантов быстрого доступа. Это очень полезно. Такие функции улучшают взаимодействие с пользователем.

Так можем ли мы построить что-то подобное? Что ж, вы делаете вызов службы при каждом нажатии клавиши и отменяете предыдущий вызов. Но в зависимости от скорости сети или скорости набора, вы можете не отменить свой запрос вовремя.

Если ваши запросы достигнут вашего сервера до того, как вы их отмените, это создаст слишком много запросов для вашего сервера, что может в конечном итоге привести к его перегрузке. Ты этого не хочешь.

Что вы можете сделать, так это использовать механизм задержки. Мы создадим экран поиска, на котором пользователь сможет написать тему и увидеть изображения, связанные с этой темой. Мы будем запрашивать два разных источника (API для Unsplash и Pexels). Начнем с основ.

‘DispatchWorkItem’

С DispatchWorkItem вы можете запустить свой блок кода в DispatchQueue и отменить его в любое время (до того, как задача будет выполнена).

Образец кода

Вы можете попробовать этот код на своей игровой площадке и увидеть результат.

Предположим, вы вызываете функцию search при каждом нажатии клавиши. Это может быть метод UITextFieldDelegate или UISearchController. Функция search выполнит эту работу.

Этот код работает достаточно хорошо. Однако это не идеальное решение. Пользователь может печатать так медленно, что задержки в одну секунду для операции может оказаться недостаточно.

Помните, здесь есть две асинхронные операции. Один задерживается, а другой - работа сети. Мы всегда отменяем первое. Было бы очень хорошо, если бы мы могли унаследовать DispatchWorkItem и переопределить метод отмены .

Сделав это, мы также отменим работу нашей сети. Но мы не можем этого сделать, потому что по какой-то причине DispatchWorkItem не является открытым классом. Если вы попытаетесь, вы увидите такое сообщение об ошибке.

Cannot inherit from non-open class 'DispatchWorkItem' outside of its defining module

Не волнуйся. Вы по-прежнему можете отменить сетевую операцию и отложить ее с каждым нажатием клавиши, используя API операции. Это еще один API, предоставляемый Apple. Я не буду вдаваться в подробности об операции в этой статье. Вы можете проверить другие статьи или блоги, если это то, что вы ищете.

«DispatchGroup»



С DispatchGroup вы можете наблюдать результаты нескольких асинхронных операций как одну задачу.

Предположим, вам нужно сделать два сетевых запроса для сбора информации о вашем пользователе. Конечно, вы можете справиться с этой ситуацией с помощью одной переменной типа bool. Но не делай этого! Было бы очень сложно справиться, если вам нужно сделать более двух сетевых запросов. Есть более простой и элегантный способ сделать это.

Выход:

getImages starting...
getFollowers starting...
Notify starting...
getImages finishing...
getFollowers finishing...
Notify finishing...

Давайте соберем их вместе

Мы собираемся использовать DispatchWorkItem и DispatchGroup для выполнения нескольких асинхронных вызовов служб к разным API. Я использовал API Unsplash и Pexels для создания примера ниже. Конечно, мы можем улучшить UX, чтобы он выглядел лучше. Но это не сегодняшняя тема, так что я пропущу.

Вернемся к коду:

Мы ждем, пока наша строка запроса не будет содержать более трех символов. Затем мы отменяем любой ожидающий запрос и создаем новый. После этого мы ищем строку запроса из каждого API в массиве services. Мы делаем его асинхронным, что означает, что все запросы выполняются одновременно (почти).

В строке 22 мы ждем результатов каждого API и вызываем обратный вызов завершения с комбинированным массивом URL-адресов. Этот процесс не запускается сразу. Вместо этого он заключен в DispatchWorkItem. Выполнение этого DispatchWorkItem откладывается каждый раз, когда функция search вызывается в строке 28).

В конце концов, DispatchWorkItem будет выполнен, и будет вызвано завершение. Как видите, вы можете легко комбинировать несколько сетевых вызовов из нескольких источников данных с помощью собственных API-интерфейсов. Вы можете найти полный исходный код внизу.

Заключение

Вам не нужно использовать сторонние библиотеки для такого рода задач. Это легко сделать с помощью собственных библиотек. Я предлагаю вам сначала изучить собственные подходы, а затем решить, использовать ли стороннюю библиотеку. Спасибо за чтение.