Скалайс-реагирующий роутер. Как выполнить ajax-запрос внутри условного маршрута
Я пытаюсь сделать несколько условных маршрутов. Условие разрешается на стороне сервера.
Пример правила маршрута:
| (dynamicRouteCT("#user" / long.caseClass[User]) ~> dynRender((page: User) => <.div("Hello, " + page.id.toString)))
.addCondition((page: User) => checkPermissions(page.id))(_ => Some(redirectToPage(Page403)(Redirect.Push)))
checkpermissions
тело:
def checkPermissions(id: Long) = CallbackTo.future{
/*Ajax.get(s"http://some.uri/?id=$id") map (res =>
* if (something) true
* else false
* )
*/
//the request before returns Future[XMLHttprequest] witch maps to Future[Boolean]
Future(false)
}
Я получил несоответствие типа здесь: (page: User) => checkPermissions(page.id)
Можно ли выполнить ajax-запрос внутри условных маршрутов?
1 ответ
Если мы посмотрим на def addCondition(cond: Page => CallbackTo[Boolean])(condUnmet: Page => Option[Action[Page]]): Rule[Page]
мы можем видеть, что это требует CallbackTo[Boolean]
, Из-за природы JS env, теперь есть путь Future[A]
в A
, Хотя это не ограничение самого scalajs-реагирует, это унаследованная реальность, которая повлияет на ваш код scalajs-реагировать; как видно из этой таблицы в документе, от CallbackTo[Future[Boolean]]
к CallbackTo[Boolean]
,
Это ограничение на уровне типов на самом деле очень полезно для взаимодействия с пользователем. Маршрутизатор является синхронным, он должен определить, как отрисовывать маршруты и изменения маршрута немедленно. Если бы это было разрешено быть асинхронным и как-то поддерживается Future
s, тогда пользователь будет испытывать заметные (и потенциально огромные) задержки без какой-либо визуальной обратной связи или средств прерывания.
"Правильный путь" для решения этой проблемы - использовать модель, которая покрывает асинхронное состояние. Вот что я бы сделал:
- Создать
AsyncState[E, A]
ADT с делами:Empty
,AwaitingResponse
,Loaded(value: A)
,Failed(error: E)
,
(Вы можете обогатить их, если хотите, например, loadTime onLoaded
повторите попыткуFailed
, время началосьAwaitingResponse
, так далее.) - Иметь экземпляр
AsyncState[Boolean]
в вашем (локальном / клиентском) состоянии. - При желании можно запустить асинхронную загрузку при запуске страницы.
- Пусть маршрутизатор передает свое значение компоненту и / или проверяет значение этого.
(Маршрутизатор не будет знать значение, потому что он динамический, используйтеCallback
в понимании, чтобы соединить вещи и удовлетворить типы.) - В зависимости от стоимости
AsyncState[Boolean]
, сделать что-то значимое для пользователя. Если этоAwaitingResponse
, отобразить маленький счетчик; если это не удалось, отобразите ошибку и, возможно, кнопку повтора.
(Следует также отметить, что AsyncState[Boolean]
на самом деле не должно быть Boolean
как это не очень описательно или верно для домена. Это, вероятно, было бы что-то более значимое, как AsyncState[UserAccess]
или что-то типа того.)
Надеюсь, это поможет! Удачи!