在同步回调中使用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>' );
);
);
现在 - 我想摆脱 '<b>' + aData[4] + '</b>'
并改用带有某些上下文的模板(这是一个简单的示例,但显示了问题)。
如果我理解正确,我不能强制 dust.js
同步渲染模板,因此可能会发生未处理的节点将被插入到文档中(用户会看到它未处理),然后当 dust.js
实际上呈现了该节点将被修改的模板。
从用户的角度来看,这显然不好看。
真的是这样吗(不能强制dust.js
同步),如果是的话 - 如何应对?我应该使用同步引擎,比如handlebars
或mustache
还是我在这里看不到明显的东西?
非常欢迎任何帮助、见解或建议。 谢谢! :)
编辑:
这个问题不是关于如何渲染模板,而是关于如何确保它在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(异步)的主要内容,如果未能解决你的问题,请参考以下文章