2013-04-26 4 views
5

В моем приложении есть динамические части, которые загружаются из базы данных в виде строки, которая выглядит как:RequireJS загрузить строку

"define(['dependency1', 'dependency2'], function(){"+ 
" // function body" + 
"})" 

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

require(["jquery"], function($){   
    $(document).ready(function(){ 
     // logic to load specific script from database 
     var scriptString = functionToLoadTheStringAbove(); 

     // ideally i would like to call it like this    
     require([scriptString], function(){ 
      // scriptString, dependency1, dependency2 are loaded 
     } 
    }); 
}); 

Как загрузить эту строку в requireJS? Я знаю о текстовом плагине, но он позволяет загружать только файлы. Я попробовал eval, но он не правильно определяет зависимости.

+0

пожалуйста ясно, задавая любой вопрос. Пожалуйста, подтвердите свой вопрос. –

+0

Ой, ты действительно хранишь анализируемый код в базе данных? –

+0

Да. В моем случае это было в расширении браузера. Таким образом, нет выбора создания конечной точки REST/сохранения динамического кода в файловой системе. – bradnoriega

ответ

5

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

Так что я в конечном итоге спросил в requireJS-форуме и изучил источник text! plugin и json! plugin. Самый чистый способ загрузить модуль из String в RequireJS - это сделать свой собственный плагин для загрузки String, а затем использовать onLoad.fromText(), который будет eval вашей Строкой и разрешит все зависимости.

Пример моего плагина (назовем его db! плагин):

define([], function(){ 
    var db = new Database(); // string is loaded from LocalStorage 
    return { 
     load: function(name, req, onLoad, reqConfig){ 
      db.get(name, function(err, scriptString){ 
       if (err) onLoad(err); 
       else onLoad.fromText(scriptString); 
      }); 
     } 
    } 
}); 

Вы можете использовать плагин, как:

require(["jquery", "db!myScript"], function($, myScript){   
    // jQuery, myScript and its dependencies are loaded from database 
}); 

Примечание:

  1. Там нет путь до require() от String без eval. Это то, что делает onLoad.fromText() внутри. Поскольку eval является злым, вы должны использовать его только в том случае, если знаете, что String вы собираетесь eval(). Если вы используете его в расширении браузера, вам может понадобиться ослабить политику CSP.
  2. Чтобы назвать свой строковый модуль, вы можете использовать explicit naming syntax. Таким образом, ваш модуль всегда будет иметь такое же абсолютное имя.
-1

Вы должны быть в состоянии сделать:

require(["jquery"], function($){   
    $(document).ready(function(){ 
     // logic to load specific script from database 
     var scriptString = functionToLoadTheStringAbove(); 

     var olddefine = define; // require js define 
     var runme; // capture function 
     define = function (args,func){ 
      runme = func; 
     } 
     eval(scriptString); 
     runme(); // run the function in current scope 
     define = olddefine; // restore requirejs function 

     // dependency1, dependency2 are loaded   
    }); 
}); 
+2

Не работает. run runme() только не разрешает зависимости + мы теряем область/закрытие, предлагаемую требованием. – bradnoriega

0

Чтобы ответить на этот вопрос немного более непосредственно, создать plugin так:

define("load-string",[], function(){ 
    var strings=[], 
     re_package_name = /^string_module_(\d+)$/; 
    return { 
     normalize: function(name, _){ 
      if(re_package_name.test(name)){ 
       return name 
      } 
      var nml = "string_module_" + (strings.push(name)-1); 
      return nml; 
     }, 
     load: function(name, _, onLoad, config){ 
      if(re_package_name.test(name)){ 
       onLoad.fromText(strings[name.match(re_package_name)[1]]); 
      }else{ 
       onLoad.error("Invalid package name: ",name); 
      } 
     } 
    } 
}); 

и использовать его так:

var world_module = "define([],function(){return 'world!'})"; 

require(["load-string!" + world_module], 
    function(x){ 
     console.log("Hello "+x); 
    }) 
Смежные вопросы