强制Julius在Yesod中重新插值,或者如何避免在客户端繁重的应用程序中对服务器进行双重标记



我的场景:一个站点显示来自持久后端的一堆行。用户可以在这些行中添加ajax样式(即不离开当前站点)。当点击提交按钮时,我希望在不加载另一个页面的情况下发生两件事:

  • 新行应该作为JSON对象发送到服务器,并添加到那里的DB中
  • 新行应立即添加到表中并且可见

此外,

  • 当用户刷新网站时,表的外观应该与添加一堆行后的相同。错误处理很棘手,但有可能,这不是我(当前)的问题

我的实现方式是:

getHomeR = do
  records ← runDB $ selectList …
  defaultLayout $ do
    $(widgetFile "tableWidget")

关键的部分是,我不想将这些行呈现为HTML服务器端,我希望发生客户端的情况,因为客户端必须能够渲染它们!(以及维护客户端和服务器端代码以完全相同的方式呈现完全相同的东西让我觉得容易出错的方法。)

因此,我通过julius插值将records放入JS变量中:

var records = #{toJSON records}; // the Haskell value containing the data.
renderRow = function(jsonObject) { … }
appendRowToTable = function(row) { … }
$(document).ready(function() {
    $.each(records, function(i,v) {
        appendRowToTable(renderRow(v));
    });
});

这是我能想出的解决这个问题最优雅的办法。它避免了必须进行单独的ajax调用来读取记录,也就是说,我知道我可以添加一个从DB中新获取记录的路由,并将其添加到JS中,但这让我觉得效率很低:它涉及到我想避免的另一个往返。相反JS和HTML是在第一个请求的基础上构建的,所有内容都在一个请求中发送快乐的一群。问题现在发生在重新加载时:


虽然records Haskell变量的内容可能在页面之间发生变化加载时,插值不会被重新评估。Yesod假设Julius文件,包括所有与IO相关的插值,保持不变,但是他们没有。我最终得到了一个records JavaScript变量,它与Haskell变量的内容,这对我来说是不可接受的。我需要触摸Julius文件以使Yesod考虑更新它(我正在使用默认脚手架。也许这就是问题所在?)


TL;DR:我将IO相关变量插入到Julius中,但如果这些变量的内容发生了变化,客户端将不会看到更新的JavaScript文件,直到我手动更改Julius文件的时间戳。我希望在IO操作的内容发生变化时重新插入JavaScript文件。或者,我们可以假设它们在每次请求时都会发生变化(即,是否有某种到期期限我可以设置为零?)

感谢阅读此墙o'文本:-)


正如Michael Snoyman所指出的,这似乎实际上是Yesod中的一个bug。我在github上打开了这个问题。

这看起来像一个bug,我可以很容易地在yesod devel站点中复制它。你能在问题跟踪器中打开一张票,这样它就不会丢失吗?

相关内容

最新更新