在同步回调中​​使用dust.js(异步)

时间:2013-04-09 17:03:22

标签: javascript asynchronous callback dust.js

我正在尝试为即将推出的项目选择一个JS模板引擎,我最喜欢的一个似乎是dust.js

我喜欢它是异步的想法,即我只是为渲染设置一些模板,当它准备就绪时,回调会将渲染的HTML插入到DOM中。

我不确定如何解决同步回调中​​的异步呈现问题。例如 - 我经常使用DataTables插件,它提供了一些回调,允许我在实际插入之前修改DOM节点。

为了说明问题 - 让我们假设我有一个以下片段(从DataTables website获取和修改):

$(document).ready( function() {
  $('#example').dataTable( {
    "fnRowCallback": function( nRow, aData, iDisplayIndex, iDisplayIndexFull ) {
      // modify the node before it's actually inserted into the document
      $('td:eq(4)', nRow).html( '<b>' + aData[4] + '</b>' );
    }
  } );
} );

现在 - 我想摆脱'<b>' + aData[4] + '</b>'并使用一些上下文渲染的模板(这是一个简单的例子,但显示了问题)。

如果我理解正确,我不能强制dust.js同步呈现模板,因此可能会发生未处理的节点将被插入到文档中(并且用户将看到它未经处理)以及稍后{ {1}}实际上呈现了将修改节点的模板。

从用户的角度来看,这显然不太好看。

情况确实如此(dust.js不能强制同步)如果是的话 - 如何处理?我应该使用同步引擎,例如dust.js还是handlebars,或者我在这里看不到明显的东西?

非常欢迎任何帮助,见解或建议。 谢谢! :)

修改

这个问题不是关于如何渲染模板,而是关于如何确保在mustache完成之前渲染它。感谢@robertklep将你的(已删除)答案指出来。

1 个答案:

答案 0 :(得分:-2)

编辑:要明确,我认为这是一种不好的做法,你通常不应该做这样的事情。我将下面的代码仅仅作为一个例子,说明如果技术或架构限制强加于你,COULD如何做这样的事情。但是,它应该永远用作最后的手段。

我过去做过一些讨厌的事情,包括使用布尔值和循环来“捕获”异步调用,但我不会真的推荐它作为一个特别好的做法。不过,如果你想要它,就在这里。

// name is the template identifier, template is the template contents,
// data is the "context" of the template (its model), callback (optional)
// is the method you want the rendered template passed to, cbContext
// (optional) is the context in which you want the callback to execute
asyncToSync = function (name, template, data, callback, cbContext) {
    // Tracks if it's time to return or not
    var finished = false;
    // Gives us an exit condition in case of a problem
    var maxLoops = 10000;
    // Create a variable to store the return value
    var outVal = 'Template rendering did not finish';
    // And the callback function to pass to dust
    var dustCb = function (err, html) {
        finished = true;
        outVal = html;
    }
    var i = 0;
    // We create this as a function so that increment goes to the bottom
    // of the execution queue, giving dustCb a chance to execute before
    // the counter hits max.
    var incrementCounter = function () {
        i += 1;
    };
    // Compile, load, and render the template
    var compiled = dust.compile(template, name);
    dust.loadSource(compiled);
    // Pass our callBack so the flag gets tripped and outVal gets set
    dust.render(name, data, dustCb);
    // count up to maxLoops
    while(!finished && (i < maxLoops)) {
        incrementCounter();
    }
    // If a callback is defined, use it
    if (callback) {
        // If a callback context is defined, use it
        return (cbContext) ? callback.call(cbContext, outVal) : callback(outVal);
    }
    // otherwise just return the rendered HTML
    return outVal;
}