简体   繁体   English

是否可以同步渲染dust.js模板?

[英]Is it possible to render dust.js templates synchronously?

I am trying to write an adapter for a client-side HTML/JS templating system to use dust.js under the hood. 我正在尝试为客户端HTML / JS模板系统编写一个适配器,以便在引擎盖下使用dust.js。 Unfortunately the API expects render operations to occur synchronously: the rendered output should be returned from the render() call. 不幸的是,API期望渲染操作同步发生:渲染输出应该从render()调用返回。 Dust.js is asynchronous and passes render output to a callback function. Dust.js是异步的,并将渲染输出传递给回调函数。 Is there any way to work around this, either in the Dust APIs or through some crazy Javascript hack? 有没有办法解决这个问题,无论是在Dust API还是通过一些疯狂的Javascript黑客攻击?

DustJS is only going to execute things asynchronously when the resources it needs to render (templates, partials) haven't already all been loaded. DustJS只会在需要渲染的资源(模板,部分)尚未加载时异步执行。

If all the dependencies of a template are loaded before you execute that template then it'll execute synchronously (as far as I can tell anyhow). 如果在执行该模板之前加载了模板的所有依赖项,那么它将同步执行(据我所知,无论如何)。 So you can do something like: 所以你可以这样做:

var result;
dust.render("tpl", data, function(err, res) {
   result = res;
});
console.log(result); // result will actually already be filled out if dustjs didn't
// have to go look for resources somewhere.

Here is a fuller example below: (and here is a jsfiddle link so you can run it: http://jsfiddle.net/uzTrv/1/ ) 下面是一个更全面的例子:(这里是一个jsfiddle链接,所以你可以运行它: http//jsfiddle.net/uzTrv/1/

<script type="text/javascript" src="dust.js"></script>
<script>
    var tpl = dust.compile("Omg {#people} {.} {/people} are here! {>partial/}", "tpl");
    var partial = dust.compile("I'm a partial but I've already been included so things still run {how}", "partial");
    dust.loadSource(tpl);
    dust.loadSource(partial);

    var data = {
        people: ["jim", "jane", "jack", "julie"],
        how: "synchronously!"
    };

    var result;
    dust.render("tpl", data, function(err, res) { 
        result = res;
    });
    console.log(result);
</script>

There could be cases (besides the one I mentioned) where I'm wrong... I don't know everything about dustjs. 可能有些情况(除了我提到的那个)我错了......我不知道关于dustjs的一切。

I too wanted to have a function that accepted a context and returned the dust rendered text. 我也想要一个接受上下文并返回灰尘渲染文本的函数。 Here is the solution I came up with: 这是我提出的解决方案:

// This function sets up dust template, and returns a new function "dusterFn()"
// dusterFn() can be passed a Context, and will return the rendered text.
// @param {String} text: The template text.
// @param {String} [name]: The name of the template to register with dust. If none is provided, a random number is used.
// @param {Function} [onError]: A function that is called if an error occurs during rendering.
function getDusterFn(text, name, onError) {

    var dusterFn = null;
    name = name || Math.floor(Math.random() * 99999).toString();
    onError = onError || function (error) { };

    try {

        var compiled = dust.compile(text, name)
        dust.loadSource(compiled);

        dusterFn = function (context) {
            var dustOutput = '';
            dust.render(name, context, function (error, out) {
                if (error) onError(error);
                dustOutput = out;
            });
            return dustOutput;
        };

    } catch (e) {
        // invalid template syntax 
        e += "\n\nPlease check your template syntax.";
        throw (e);
    }

    return dusterFn;

}

Usage 用法

var greetingTemplate = getDusterFn('Hello {name}, You are {age} years old!');
greetingTemplate({name: 'Jane', age: 24});

Matt's solution gave me some pointers on how to write a little wrapper that hides the "ugliness" of his solution (by "ugliness" I mean declaring variable outside of callback, assigning value inside callback and returning outside callback). Matt的解决方案给了我一些关于如何编写一个隐藏其解决方案“丑陋”的小包装器的指针(“丑陋”我的意思是在回调之外声明变量,在回调中分配值并返回外部回调)。

It not only wraps the hack into a little function but also binds the template´s name. 它不仅将hack包装成一个小函数,还绑定了模板的名称。 I find this incredible helpful as I find myself using the same render function over and over again, but I do not want to specifiy the template´s name every time. 我觉得这很有帮助,因为我发现自己一遍又一遍地使用相同的渲染功能,但我不想每次都指定模板的名称。

function templates(template) {
  return function templatesWrapper(data) {
    var result;
    dust.render(template, data, function onRender(err, data) {
      if (err) {
        throw err;
      }
      result = data;
    });
    return result;
  }
}

This is how to use it: 这是如何使用它:

var renderHello = templates('hello.html');
renderHello({ username: 'Stackoverflow' });
// => <h1>Hello, Stackoverflow</h1>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM