0

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

路由规则示例:

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

4

1 回答 1

1

如果我们看一下,def addCondition(cond: Page => CallbackTo[Boolean])(condUnmet: Page => Option[Action[Page]]): Rule[Page]我们可以看到它需要一个CallbackTo[Boolean]. 由于 JS 环境的性质,现在有办法Future[A]A. 虽然它不是 scalajs-react 本身的限制,但它是一个继承的现实,会影响你的 scalajs-react 代码;正如文档中的这张表所示,没有办法从 aCallbackTo[Future[Boolean]]转到 a CallbackTo[Boolean]

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

解决此问题的“正确方法”是使用涵盖异步状态的模型。这就是我要做的:

  1. 使用案例创建AsyncState[E, A]ADT:Empty, AwaitingResponse, Loaded(value: A), Failed(error: E).
    (如果需要,您可以进一步丰富这些内容,例如 loadTime on Loaded、 retry callback on Failed、 timeStarted onAwaitingResponse等)
  2. AsyncState[Boolean]在您的(本地/客户端)状态中有一个实例。
  3. 可选择在页面启动时启动异步加载。
  4. 让路由器将其值传递给组件和/或检查 this 的值。
    (路由器不知道该值,因为它是动态Callback的,用于理解以连接事物并满足类型。)
  5. 根据 的值AsyncState[Boolean],呈现对用户有意义的东西。如果是AwaitingResponse,则显示一个小微调器;如果失败,则显示错误,并且可能会显示重试按钮。

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

希望有帮助!祝你好运!

于 2018-07-07T03:07:06.687 回答