2013-04-09 4 views
2

Я пытаюсь выбрать механизм шаблона JS для предстоящего проекта, и один из моих фаворитов, похоже, dust.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 оказывать шаблон синхронно, так что может случиться так, что необработанный узел будет вставлен в документ (и пользователи будут видеть это необработанный), а позже, когда на самом деле dust.js Отрисовывает шаблон, который будет модифицирован.

Это, очевидно, не будет выглядеть с точки зрения пользователя.

Так это действительно так (dust.js не может быть принудительно синхронным), и если да - как с этим справиться? Должен ли я использовать синхронный двигатель, например handlebars или mustache, или, может быть, я не вижу здесь ничего очевидного?

Любая помощь или понимание или совет были бы очень желанными. Спасибо! :)

EDIT:

Этот вопрос не о том, как сделать шаблон, но о том, как убедиться, что он оказывается перед fnRowCallback отделки. Спасибо @robertklep за то, что указали это на ваш (удаленный) ответ.

+0

Исключено, потому что я понял, что это был не ответ на ваш вопрос :) Во всяком случае, вы не можете заставить асинхронную функцию, чтобы быть готов до 'финиширует fnRowCallback', так что если это действительно проблема, я не думаю, Dust.js можно использовать. – robertklep

+0

Да, я заметил - спасибо за попытку помочь! :) И да - это то, о чем я беспокоился - есть некоторые библиотеки, которые ожидают, что вы вернетесь (или сделаете) что-то от синхронного обратного вызова, и dust.js могут не играть с ними слишком хорошо :( – kgr

ответ

-2

Редактировать: Чтобы быть ясным, я считаю, что это плохая практика, и вы обычно не должны делать такие вещи. Я включил приведенный ниже код просто в качестве примера того, как один из них мог бы сделать что-то подобное, если технические или архитектурные ограничения заставили его действовать. Однако его следует использовать только в качестве крайней меры.

В прошлом я делал некоторые неприятные вещи, которые связаны с использованием логического цикла и цикла для «захвата» асинхронных вызовов, но я бы не рекомендовал его в качестве особенно хорошей практики. Тем не менее, если вы этого хотите, вот оно.

// 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; 
} 
+0

Если это плохая практика , не делайте это потенциальным ответом. – Trevor

+1

Не говоря уже об этом, все будет заблокировано. – Trevor

+0

Я не саркастически и не пытался быть грубым. Если вам нужно прибегнуть к «неприятным вещам», тогда вы должны пересмотреть свой дизайн. Кстати, также не полезно продвигать плохие практики. Получите навыки некоторых людей. – Trevor

Смежные вопросы