2013-04-26 46 views
5

在我的应用程序有一些是从数据库加载为字符串,看起来像动态部分:RequireJS加载字符串

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

这仅仅是一个简单的requireJS模块,作为一个字符串。我想懒惰加载上面的脚本使用async require调用。所以,我的主要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

请明确一边询问任何问题。请把你的问题告诉你。 – 2013-04-26 03:55:13

+0

哦,我的,你真的在​​像这样的数据库中存储可评估的代码吗? – 2015-10-26 02:06:48

+0

是的。在我的情况下,它是在浏览器扩展。因此,没有选择在文件系统中创建REST端点/保存动态代码。 – bradnoriega 2016-03-04 03:42:24

回答

5

这是相当晚了,但我只是张贴我的解决方案在这里任何人的情况下需要。

所以我最终要求在requireJS论坛和检查text! pluginjson! plugin的来源。在RequireJS中从String中加载模块的最简单的方法是通过制作自己的插件来加载字符串,然后使用onLoad.fromText()这将eval您的String并解决所有依赖关系。我的插件的

例(姑且称之为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()的方式,无eval。这是onLoad.fromText()在内部做的。既然eval是邪恶的,那么只有在你知道什么字符串时你才应该使用它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

它不起作用。运行runme()只能解决依赖性问题+我们失去了由require提供的scope/closure。 – bradnoriega 2013-04-26 04:51:47

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