Скалайс-реагирующий роутер. Как выполнить ajax-запрос внутри условного маршрута - PullRequest
0 голосов
/ 04 июля 2018

Я пытаюсь составить несколько условных маршрутов. Условие разрешается на стороне сервера.

Пример правила маршрута:

| (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 Ответ

0 голосов
/ 07 июля 2018

Если мы посмотрим на 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] или что-то в этом роде.)

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

...