scalajs 反应路由器。如何在条件路由中执行 ajax 请求

scalajs-react router. How to perform ajax request inside conditional route

我正在尝试制作一些有条件的路线。条件在服务器端解决。

路由规则示例:

| (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 请求?

如果我们查看 def addCondition(cond: Page => CallbackTo[Boolean])(condUnmet: Page => Option[Action[Page]]): Rule[Page],我们会发现它需要一个 CallbackTo[Boolean]。由于 JS 环境的性质,现在有从 Future[A]A 的方法。虽然这不是 scalajs-react 本身的限制,但它是一个继承的现实,会影响你的 scalajs-react 代码;正如 this table in the doc 所示,无法从 CallbackTo[Future[Boolean]] 变为 CallbackTo[Boolean]

这种类型级别的限制对于用户体验来说其实是一件非常好的事情。路由器是同步的,它必须立即决定如何渲染路由和路由变化。如果它被允许异步并以某种方式支持 Futures,那么用户将在没有任何视觉反馈或中断方式的情况下体验明显的(并且可能是巨大的)延迟。

"right way"解决这个问题的方法是使用覆盖异步状态的模型。这就是我要做的:

  1. 创建一个 AsyncState[E, A] ADT 案例:EmptyAwaitingResponseLoaded(value: A)Failed(error: E)
    (如果需要,您可以进一步丰富这些,例如 Loaded 上的 loadTime、Failed 上的重试回调、AwaitingResponse 上的 timeStarted 等)
  2. 在您的(local/client-side)状态下有一个 AsyncState[Boolean] 实例。
  3. 可选择在页面启动时启动异步加载。
  4. 让路由器将其值传递给组件and/or检查此值。
    (路由器不知道该值,因为它是动态的,请使用Callback 在理解中将事物连接起来并满足类型。)
  5. 根据 AsyncState[Boolean] 的值,呈现对用户有意义的内容。如果是 AwaitingResponse,显示一个小旋转器;如果失败则显示错误并可​​能显示重试按钮。

(还应注意,AsyncState[Boolean] 实际上不应该是 Boolean,因为这对域的描述性或真实性不强。它可能更有意义,例如 AsyncState[UserAccess] 或类似的东西。)

希望对您有所帮助!祝你好运!