2

我目前正在使用服务器端的lift和d3(一个javascript可视化框架)来实现一个图形可视化工具,用于所有可视化。我遇到的问题是在脚本中我想从服务器获取会话相关数据。

所以基本上,我的目标是在静态 js 脚本中编写提升有效的 ajax 回调。

到目前为止我尝试过的

如果您认为最好的解决方案是我已经尝试过的解决方案,请随时发布详细的答案,告诉我如何准确使用它以及它如何完全解决我的问题。

使用lift在另一个脚本中编写ajax回调并从主脚本中调用它

这种类似于隐藏文本输入的解决方案可能更有可能起作用。但是它并不优雅,这意味着我必须在加载时加载很多脚本,这并不方便。

正如邮件列表上的讨论中所解释的,这似乎是电梯社区中首选的解决方案之一。

REST接口

通常,从 lift 中的 javascript 函数获取数据的方法是创建一个 REST 接口。但是,此界面不会链接到任何会话。这是我从上一个问题中得到的解决方案:Get json data in d3 from lift snippet

将函数作为脚本的参数

另一种解决方案是将 ajaxcallback 作为调用以生成我的图形的主脚本的参数。但是我希望有很多回调,我不想弄乱我的脚本的参数。

在lift中编写整个脚本,然后将其提供给客户端

这个解决方案可以很优雅,但是我的脚本很长,我真的希望它保持静态。

我想要的是

在客户端

在查看我网页的源代码时,我发现 ajaxSelect 的回调是:

<select onchange="liftAjax.lift_ajaxHandler('F966066257023LYKF4=' + encodeURIComponent(this.value), null, null, null)" name="F96606625703QXTSWU" id="node_delete" class="input">

此外,网页末尾还有一个包含页面状态的变量:

var lift_page = "F96606625700QRXLDO";

所以,我想知道是否可以使用这个liftAjax.lift_ajaxHandler函数来模拟我的 ajaxcall 是有效的。但是我不知道要使用的确切合成器。

在服务器端

由于我在客户端“伪造”了一个请求,我现在想在客户端获取请求并将其分派给正确的函数。这是LiftRules.dispatch对象似乎是最好的解决方案的地方:当它被调用时,所有会话管理都已完成(请求已验证并链接到会话),但是我不知道如何在append功能。

评论

在 lift 中,所有变量的名称都更改为随机字符串以提高安全性,我希望在我的应用程序中具有相同的行为,即使这可能意味着我将不得不“给”javascript 这些值。然而,一个 15 个字符串值的数组仍然比 15 个函数作为 javascript 函数的参数更好。

编辑

在跟踪我的研究时,我发现了这个页面:将服务器功能映射到客户端操作,它以某种方式解释了命名函数的目标,即使它仍然没有引导我找到一个可行的解决方案。

4

1 回答 1

6

快速回答

在电梯中休息不必是无国籍的。如果您使用 LiftRules.dispatch.append 注册您的 RestHelper,那么它将被有状态地处理,并且会话信息将照常通过 S 对象提供。

长答案

既然您似乎很感兴趣,而且它之前就出现过,这里有一个更详细的解释,说明如何在 Lift 中注册和调用服务器端函数。如果您有一段时间没有使用 Lift,请移开视线。以下内容不应以任何方式用于评估 Lift 或其复杂性。这纯粹是库开发人员级别的东西,大多数 Lift 用户在进行开发时都没有意识到这一点。

这个怎么运作

当您创建有状态回调时,通常使用 SHtml 对象中的方法,您真正要做的是在用户会话的上下文中注册 S.AFuncHolder 类型的对象,每个对象都有一个唯一的 ID。在此过程中生成的唯一 ID 就是您遇到类似模式时所看到的F96606625700QRXLDO. 当通过表单 post、ajax 或其他方式提交数据时,Lift 将检查对这些函数 ID 的请求并执行相关函数(如果存在)。有几个助手可以提供更具体的 AFuncHolder 类型,例如 S.SFuncHolder(接受单个字符串查询参数)和 S.BinFuncHolder(参数是多部分表单数据),但它们都返回 Any 并且在幕后 Lift 将收集这些返回值创建正确类型的响应。例如,一个 JsCmd 将产生一个执行命令的 JavaScriptResponse。您也可以直接返回 LiftResponse。

如何使用它

AFuncHolders 使用 S.fmapFunc 方法注册。你会这样称呼它

S.fmapFunc(SFuncHolder({ (str: String) =>
  doSomethingAwesomeWithAString(str)
}))(id => <input type="text" name={id} value=""/>)

第一个参数是你的函数,包装在正确的 *FuncHolder 类型中,第二个参数是一个函数,它接受生成的 id 并输出something。获得输出的内容就是您将包含在页面上的内容。它应该以某种方式导致将 id 作为查询参数发送到服务器,以便执行您的函数。

把它们放在一起

您可以使用上述方法进行自己的 Ajax 调用,但是当 Lift 进行 ajax 调用时,还有一些其他注意事项:

1) 大多数浏览器只允许同时连接到一个给定的域。三似乎是一个神奇的数字。2) AFuncHolders 通常会关闭它们所包含的片段的范围,如果一次处理多个 ajax 请求,每个请求都在自己的线程中,可能会发生不好的事情。

为了解决这些问题,该liftAjax.lift_ajaxHandler函数对每个 ajax 请求进行排队,确保一次只将一个请求发送到服务器。

这种方法的缺点是,在需要将结果传递给回调的地方进行 Ajax 调用会很困难。例如,JQuery 自动完成功能在接受匹配列表的输入更改时提供回调函数。如果您手动调用 LiftAjax.lift_ajaxHandler,您可以为成功和错误提供自己的回调函数,我建议您在浏览器中查看这些函数的源代码,以获取有关它们如何工作的更多信息。

实际上还有更多内容,例如 Lift 如何在 ajax 回调中恢复 RequestVars(这是 lift_page 的来源,但这就是我准备在周六早上喝咖啡时解释的全部内容:)

祝你的应用好运!

于 2012-11-17T16:39:13.767 回答