¿Es posible renderizar las templates dust.js sincrónicamente?

Estoy tratando de escribir un adaptador para un sistema de templates HTML / JS del lado del cliente para usar dust.js debajo del capó. Lamentablemente, la API espera que las operaciones de representación se produzcan de forma síncrona: la salida representada debe devolverse desde la llamada a render (). Dust.js es asíncrono y pasa la salida de renderizado a una function de callback. ¿Hay alguna forma de evitar esto, ya sea en las API de polvo o a través de algún truco loco de Javascript?

DustJS solo ejecutará cosas de forma asíncrona cuando los resources que necesita para procesar (templates, parciales) no se hayan cargado todavía.

Si todas las dependencies de una plantilla se cargan antes de ejecutar esa plantilla, se ejecutará de forma síncrona (hasta donde sé de todos modos). Entonces puedes hacer algo como:

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. 

Aquí hay un ejemplo más completo a continuación: (y aquí hay un enlace jsfiddle para que pueda ejecutarlo: 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> 

Podría haber casos (además del que mencioné) en los que estoy equivocado … No sé todo sobre dustjs.

Yo también quería tener una function que aceptara un context y devolviera el text generado. Aquí está la solución que se me ocurrió:

 // This function sets up dust template, and returns a new function "dusterFn()" // dusterFn() can be passed a Context, and will return the rendenetworking 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; } 

Uso

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

La solución de Matt me dio algunos consejos sobre cómo escribir una pequeña envoltura que oculta la "fealdad" de su solución (por "fealdad" me refiero a declarar variable fuera de la callback, asignar valor a la callback y devolver la devolución externa).

No solo envuelve el truco en una pequeña function sino que también vincula el nombre de la plantilla. Encuentro esto increíblemente útil ya que me encuentro usando la misma function de renderizado una y otra vez, pero no quiero especificar el nombre de la plantilla cada vez.

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

Esta es la forma de usarlo:

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