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

Posted

技术标签:

【中文标题】在同步回调中​​使用dust.js(异步)【英文标题】:Using dust.js (asynchronous) in synchronous callbacks 【发布时间】:2013-04-01 05:52:55 【问题描述】:

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

我喜欢它是异步的想法,即我只是暂存一些模板进行渲染,当它准备好时,回调将渲染的 html 插入到 DOM 中。

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

为了说明问题 - 假设我有以下 sn-p(取自 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>' );
    
   );
 );

现在 - 我想摆脱 '&lt;b&gt;' + aData[4] + '&lt;/b&gt;' 并改用带有某些上下文的模板(这是一个简单的示例,但显示了问题)。

如果我理解正确,我不能强制 dust.js 同步渲染模板,因此可能会发生未处理的节点将被插入到文档中(用户会看到它未处理),然后当 dust.js实际上呈现了该节点将被修改的模板。

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

真的是这样吗(不能强制dust.js 同步),如果是的话 - 如何应对?我应该使用同步引擎,比如handlebarsmustache 还是我在这里看不到明显的东西?

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

编辑:

这个问题不是关于如何渲染模板,而是关于如何确保它在fnRowCallback 完成之前被渲染。感谢@robertklep 用您的(已删除)答案指出这一点。

【问题讨论】:

已删除,因为我意识到这不是您问题的答案 :) 无论如何,您不能强制异步函数在 fnRowCallback 完成之前准备好,所以如果这真的是一个问题,我不会'认为 Dust.js 不可用。 是的,我注意到了 - 感谢您的帮助! :) 是的 - 这就是我担心的 - 有一些库希望你从同步回调中​​返回(或做)某些事情,而dust.js 可能无法很好地与它们配合使用:( 【参考方案1】:

编辑:明确地说,我认为这是一种不好的做法,您通常不应该这样做。我包含下面的代码只是作为一个示例,如果技术或架构限制迫使您这样做,一个人如何做这样的事情。但是,它只能作为最后的手段使用。

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

// 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;

【讨论】:

如果这是不好的做法,不要让它成为潜在的答案。 更不用说这会阻止一切。 我不是在讽刺或试图变得粗鲁。如果您需要求助于“讨厌的东西”,那么您应该重新考虑您的设计。顺便说一句,推广不良做法也无济于事。掌握一些人际交往能力,伙计。 我没有投反对票。下马。 :P 另外,当我写评论时,答案并没有包含“不良做法”这个词。 如果我说某事不是一个好的做法,那么它有点暗示这是一个不好的做法。抱歉,我以为你是反对票,因为没有其他人留下任何 cmets 我只是假设是你。我的错。

以上是关于在同步回调中​​使用dust.js(异步)的主要内容,如果未能解决你的问题,请参考以下文章

同步回调函数与异步回调函数

立即从同步代码执行异步回调

php支付宝手机网站支付,异步回调和同步回调里面应该怎么写

同步调用,异步回调和 Future 模式

如何优雅的处理Nodejs中的异步回调

js同步-异步-回调