Подтвердить что ты не робот

Можно ли синхронно отображать шаблоны dust.js?

Я пытаюсь написать адаптер для клиентской HTML/JS templating системы, чтобы использовать dust.js под капотом. К сожалению, API ожидает, что операции рендеринга будут выполняться синхронно: выводимый вывод должен быть возвращен из вызова render(). Dust.js является асинхронным и передает результат вывода функции обратного вызова. Есть ли способ обойти это, либо в API Пыли, либо через какой-то сумасшедший взлом Javascript?

4b9b3361

Ответ 1

DustJS будет выполнять асинхронно выполнение, когда ресурсы, необходимые для рендеринга (шаблоны, частичные), еще не были загружены.

Если все зависимости шаблона загружаются до того, как вы запустите этот шаблон, он будет выполняться синхронно (насколько я могу сказать так или иначе). Поэтому вы можете сделать что-то вроде:

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.

Ниже приведен более полный пример: (и вот ссылка 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>

Могут быть случаи (помимо того, о чем я упоминал), где я ошибаюсь... Я не знаю все о пылях.

Ответ 2

Я тоже хотел иметь функцию, которая приняла контекст и вернула текст, обработанный пылью. Вот решение, которое я придумал:

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

}

Использование

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

Ответ 3

Решение Matt дало мне несколько указаний на то, как написать небольшую обертку, которая скрывает "уродство" его решения ( "уродством" я подразумеваю объявление переменной вне обратного вызова, назначение значения внутри обратного вызова и возврат внешнего обратного вызова).

Он не только обертывает хак в маленькую функцию, но также связывает имя шаблона. Я нахожу это невероятным полезным, поскольку я снова и снова использую одну и ту же функцию рендеринга, но я не хочу указывать имя шаблона каждый раз.

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

Вот как это использовать:

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