2013-04-26 96 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); 
    })