从静态javascript中提取会话有效的ajax回调



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

因此,基本上,我的目标是在静态js脚本中编写lift有效的ajax回调。

到目前为止我已经尝试了什么

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

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

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

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

REST接口

通常,要从lift中的javascript函数获取数据,需要创建一个REST接口。但是,此接口不会链接到任何会话。这是我从上一个问题中得到的解决方案:从提升片段中获取d3中的json数据

将函数作为脚本的参数

另一个解决方案是将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个字符串值的数组仍然比作为javascript函数参数的15个函数更好。

编辑

在进行研究的过程中,我发现了以下页面:将服务器功能映射到客户端操作,这在某种程度上解释了命名功能的目标,即使它仍然没有让我找到一个有效的解决方案。

快速回答

电梯休息不一定是无状态的。如果您使用LiftRules.dispatch.append注册RestHelper,那么它将被状态处理,会话信息将像往常一样通过S对象可用。

答案很长

由于您似乎很感兴趣,而且之前在SO上也提到过,下面将更详细地解释如何在Lift中注册和调用服务器端函数。如果您已经有一段时间没有使用Lift了,请将目光移开。以下内容不应以任何方式用于评估电梯或其复杂性。这纯粹是库开发人员级别的东西,大多数Lift用户在进行开发时都没有意识到这一点

它的工作原理

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

如何使用

AFunc持有者使用S.fmapFunc方法注册。你可以这样称呼它

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

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

把它们放在一起

您可以使用上面的内容来进行自己的Ajax调用,但当Lift进行Ajax调用时,还有一些其他注意事项:

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

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

这种方法的缺点是,在需要将结果传递给回调的情况下,很难进行Ajax调用。例如,JQuery autocomplete在输入更改时提供了一个回调函数,接受匹配列表。如果您手动调用LiftAjax.lift_axHandler,那么您可以为成功提供自己的回调函数&错误,我建议您在浏览器中查看这些函数的来源,以了解有关它们如何工作的更多信息。

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

祝你的应用程序好运!

最新更新