Узнайте, как создавать простые источники данных WebSocket с функциями приостановки
В этой истории мы узнаем, как связываться с различными сопрограммами и использовать их для реализации удаленного источника данных с функциями, которые выглядят как локальные функции. Эти функции представляют собой запрос, возвращающий ответ с использованием WebSocket под тканью.
Мотивация
Когда я писал источник данных, который внутренне использует соединение WebSocket, я заметил, что шаблон сокета отправки/получения увеличивает сложность программного обеспечения и сложность сопровождения. Отправьте запрос, и получение ответа в другой части кода заставит программиста объявить временные переменные для использования в коде ответа.
Представьте, если бы можно было отправить запрос и приостановить его до тех пор, пока не будет получен ответ, а затем возобновить его. Как и в приведенном ниже коде, источник данных предоставляет удобную функцию приостановки входа в систему, которая возвращает результат входа (полный код в конце):
SuspendMediator решает проблему
Что ж, с SuspendMediator
это возможно! SuspendMediator
— это моя реализация только с двумя методами: приостановить и возобновить.
Обратите внимание, что две функции получают ключ исключительно для идентификации запроса и ответа. Предположим, что этот запрос имеет идентификатор сообщения, отправленный обратно в ответ. Этот идентификатор может быть ключом к этому сообщению. Чем более «уникальным» является ключ, тем больше параллельных запросов может быть, потому что дубликаты ключей должны ожидать в очереди запросов. Это ограничение необходимо для того, чтобы SuspendMediator
знал, кто однозначно сопоставляет отправленный запрос с полученным ответом.
Выполнение
SuspendMediator
может иметь несколько реализаций, с очередью для запросов или без, с тайм-аутами запроса/очереди и так далее.
Очередь запросов используется для кэширования запросов с одним и тем же ключом или предотвращения параллельных запросов:
- НЕТ ОЧЕРЕДИ: Выполнения с разными ключами могут выполняться параллельно, но когда
SuspendMediator
обнаруживает дублирующийся ключ, выдает ошибку в методе приостановки. - ENQUEUE SAME KEY: Выполнения с разными ключами могут выполняться параллельно и ставить в очередь дубликаты ключей.
- ОБЕСПЕЧЬТЕ ПОРЯДОК: Избегайте параллельных казней. Он отправляет их один за другим, ожидая ответа по порядку.
У нас может быть два типа тайм-аута:
- Тайм-аут очереди: тайм-аут используется, когда у нас есть дубликаты ключей, и необходимо подождать в очереди, чтобы выполнить запрос.
- Время ожидания запроса: время ожидания, используемое для предотвращения ожидания ответа, который никогда не будет получен.
Хватит болтать. Покажите мне код:
Примеры использования SuspendMediator
Основная цель SuspendMediator
— взаимодействие между сопрограммами. Предположим, что пинг-понг из трех сопрограмм умножает число на два несколько раз.
Выход:
Coroutine 1 - result1 Success(5) Coroutine 2 - result2 Success(10) Coroutine 3 - result3 Success(20) Coroutine 1 - result4 Success(40)
Сопрограмма 1 приостанавливается с помощью ключа 1 до тех пор, пока сопрограмма 2 не возобновит работу этого ключа со значением 5. Сопрограмма 1 возобновляет получение значения и отправляет двойное это значение с помощью ключа 2. Значение ключа 3 создается в сопрограмме 2 и отправляется сопрограмме 3, и скоро. Обратите внимание, что SuspendMediator
— это не производитель/потребитель, а способ двунаправленной связи между сопрограммами.
Более интересным примером является использование функции обратного вызова функции приостановки. Когда действие вызывается и возвращает true, гарантируется, что ключ готов для возобновления другого вызова сопрограммы с этим ключом.
Возвращаясь к примеру входа в систему в начале истории, представьте себе этот простой протокол строки входа:
Request: 1|username|password Response: 1|loginResult
Обратите внимание, что первое поле представляет тип сообщения (логин), который в этом примере имеет значение 1, и мы можем использовать его в качестве ключа сообщения. Протокол может быть реализован с использованием запечатанных классов следующим образом:
Давайте посмотрим пример кода DataSource
с использованием SuspendMediator
:
Когда вызывается функция входа в систему, функция приостанавливается до тех пор, пока в очереди queuedSuspendMediator
не останется ключа со значением 1, поскольку queueMode
равно ENQUEUE_SAME_KEY
. В простом случае очередь пуста или не имеет ключа 1, поэтому приостановка не требуется.
После этого вызывается WebSocket sendMessage
со значением LoginRequest
. Когда сервер отвечает, прослушиватель анализирует сообщение и вызывает функцию возобновления с сообщением LoginResult
.
Заключение
С SuspendMediator
мы можем писать более простые коды с меньшей сложностью временных переменных для сообщений запроса и ответа. WebSocket DataSource — один из многих вариантов использования SuspendMediator
.
Спасибо за прочтение. Оставайтесь с нами, чтобы узнать больше.