Скалайс-реагирующий роутер. Как выполнить 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, тогда пользователь будет испытывать заметные (и потенциально огромные) задержки без какой-либо визуальной обратной связи или средств прерывания.

"Правильный путь" для решения этой проблемы - использовать модель, которая покрывает асинхронное состояние. Вот что я бы сделал:

  1. Создать AsyncState[E, A] ADT с делами: Empty, AwaitingResponse, Loaded(value: A), Failed(error: E),
    (Вы можете обогатить их, если хотите, например, loadTime on Loaded повторите попытку Failed , время началось AwaitingResponse , так далее.)
  2. Иметь экземпляр AsyncState[Boolean] в вашем (локальном / клиентском) состоянии.
  3. При желании можно запустить асинхронную загрузку при запуске страницы.
  4. Пусть маршрутизатор передает свое значение компоненту и / или проверяет значение этого.
    (Маршрутизатор не будет знать значение, потому что он динамический, используйте Callback в понимании, чтобы соединить вещи и удовлетворить типы.)
  5. В зависимости от стоимости AsyncState[Boolean], сделать что-то значимое для пользователя. Если это AwaitingResponse, отобразить маленький счетчик; если это не удалось, отобразите ошибку и, возможно, кнопку повтора.

(Следует также отметить, что AsyncState[Boolean] на самом деле не должно быть Boolean как это не очень описательно или верно для домена. Это, вероятно, было бы что-то более значимое, как AsyncState[UserAccess] или что-то типа того.)

Надеюсь, это поможет! Удачи!

Другие вопросы по тегам