【问题标题】:Waiting for Jinja to fully finish rendering a page before executing a script在执行脚本之前等待 Jinja 完全完成页面渲染
【发布时间】:2019-06-04 11:42:28
【问题描述】:

是否可以在执行某个脚本之前等待Jinja2 完成插入所有模板元素?我正在尝试在页面上使用KaTeX 呈现一些数学,该页面还包含一堆模板块。但是,数学是在所有模板块被 Jinja2 渲染之前渲染的,所以这些块中的任何数学都不会渲染。

我可以设置一个超时时间,比如 5 秒,然后执行渲染脚本(这可行),但我宁愿使用更优雅的解决方案。按照指示在<script> 标签内使用defer here 什么都不做,也没有

<script>
    document.addEventListener("DOMContentLoaded", function() {
        renderMathInElement(document.body, {
            // ...options...
        });
    });
</script>

event 是什么告诉浏览器模板引擎如 Jinja2 已经完成工作?肯定不是DOMContentLoaded,基于以上。

编辑

Here 是使用A+ LMS 实施的示例课程。麻烦的模板可以在文件夹_templates 中找到。默认模板使用 MathJax,但由于那个特定的库有一些烦人的特性,例如当需要渲染大量数学时速度很慢,所以我决定改用 KaTeX。这是我的模板版本:

{% extends "aplus/layout.html" %}

{% block extrahead %}

<!--  MathJax (LaTex math)
<script type="text/javascript" async src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/MathJax.js?config=TeX-MML-AM_CHTML" data-aplus></script>
 -->

<!--  KaTeX (LaTeX math) -->

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.10.2/dist/katex.min.css" integrity="sha384-yFRtMMDnQtDRO8rLpMIKrtPCD5jdktao2TV19YiZYWMDkUR5GQZR/NOVTdquEx1j" crossorigin="anonymous" data-aplus>
<script defer type="text/javascript" src="https://cdn.jsdelivr.net/npm/katex@0.10.2/dist/katex.min.js" integrity="sha384-9Nhn55MVVN0/4OFx7EE5kpFBPsEMZxKTCnA+4fqDmg12eCTqGi6+BB2LjY8brQxJ" crossorigin="anonymous"  onload="console.log('Hello, this is KaTeX!');" data-aplus></script>
  <script data-aplus>
    function render_katex() {
      if (window.katex) {
          renderMathInElement(document.body,{delimiters: [
          {left: "\\[", right: "\\]", display: true},
          {left: "\\(", right: "\\)", display: false}]}
          );
        console.log("Math rendered.");
      } else {
        console.log("KaTeX not loaded.")
      };
    };
  </script>

<script defer type="text/javascript" src="https://cdn.jsdelivr.net/npm/katex@0.10.2/dist/contrib/auto-render.min.js" integrity="sha384-kWPLUVMOks5AQFrykwIup5lo0m3iMkkHrD0uJ4H5cjeGihAutqP0yW0J6dpFiVkI" crossorigin="anonymous" onload="setTimeout(render_katex,300);" data-aplus></script>


<!-- Custom course styles -->
<link rel="stylesheet"
      href="{{ pathto('_static/course.css', 1) }}"
      type="text/css"
      data-aplus />

<link rel="stylesheet"
      href="{{ pathto('_static/active_element.css', 1) }}"
      type="text/css"
      data-aplus />

{% endblock %}

编辑 2

A link 到 Pastebin 页面的完整源代码。

【问题讨论】:

  • 顺序是: 1. Jinja2 渲染模板 2. 生成的文档从服务器发送到客户端(浏览器) 3. 客户端 JavaScript 开始运行 - 无论是什么问题,它都需要固定在服务器端。您可以发布重现该问题的 Jinja2 模板代码吗?
  • @ChrisG 我已经编辑了我的问题并添加了相关链接 + 我的模板版本导致问题。
  • 当您观察到并非所有数学块都被渲染时,您是否收到任何控制台错误?
  • 没有。只有两个关于onmozfullscreenchangeonmozfullxcreenerror 的弃用警告由translate.js 发出。但就像我说的,如果我等待至少一秒钟(或者在包含大量元素的大页面上等待十秒钟),似乎没有问题。
  • 能否在浏览器中查看源码(Ctrl+U)并粘贴到pastebin之类的地方?您的问题的问题在于它实际上并不包含重现该问题的代码,这意味着无法调试它。

标签: javascript timeout jinja2 katex


【解决方案1】:

好的,所以我得出的结论是,最好的选择是简单地等待模板通过 Jinja2。一个人应该等多久?嗯,这取决于一个页面上有多少练习:

<!--  KaTeX (LaTeX math) -->

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.10.2/dist/katex.min.css" integrity="sha384-yFRtMMDnQtDRO8rLpMIKrtPCD5jdktao2TV19YiZYWMDkUR5GQZR/NOVTdquEx1j" crossorigin="anonymous" data-aplus>
<script defer type="text/javascript" src="https://cdn.jsdelivr.net/npm/katex@0.10.2/dist/katex.min.js" integrity="sha384-9Nhn55MVVN0/4OFx7EE5kpFBPsEMZxKTCnA+4fqDmg12eCTqGi6+BB2LjY8brQxJ" crossorigin="anonymous"  onload="console.log('Hello, this is KaTeX!');" data-aplus></script>
<script defer type="text/javascript" src="https://cdn.jsdelivr.net/npm/katex@0.10.2/dist/contrib/auto-render.min.js" integrity="sha384-kWPLUVMOks5AQFrykwIup5lo0m3iMkkHrD0uJ4H5cjeGihAutqP0yW0J6dpFiVkI" crossorigin="anonymous" data-aplus></script>

<script data-aplus>
  document.addEventListener("DOMContentLoaded", function() {

    const n_of_exercises = $(".exercise").length;
    // Using "let" here so that math would render also the first time a page is loaded
    const ms = 300;
    const render_time = n_of_exercises * ms;
    const minimum_render_time = 1200;

    if (render_time >= minimum_render_time) {

      setTimeout(function() {
        renderMathInElement(document.body,{delimiters: [
          {left: "\\[", right: "\\]", display: true},
          {left: "\\(", right: "\\)", display: false}]}
        );
      }, render_time);

    } else {

      setTimeout(function() {
        renderMathInElement(document.body,{delimiters: [
          {left: "\\[", right: "\\]", display: true},
          {left: "\\(", right: "\\)", display: false}]}
        );
      }, minimum_render_time);

    };

    console.log("Number of .exercise divs:" + n_of_exercises);
    console.log("Render time:" + render_time);


  });
</script>

事实证明,无论页面上有多少练习,事情发生仍然需要一些最少的时间。这就是指定minimum_render_time 的原因。这仅在此特定页面上进行了测试,因此将来可能需要稍微移动值。

【讨论】:

  • 再次重申:您不必“等待模板通过 Jinja2”。在 Jinja2 完成模板渲染之前,任何客户端 JavaScript 代码都不可能开始执行。这个答案充其量是一种解决方法,并不能解决问题。
猜你喜欢
  • 2013-02-17
  • 1970-01-01
  • 2020-06-17
  • 2021-11-21
  • 2021-01-03
  • 2018-05-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多