2013-04-26 10 views
5

W mojej aplikacji są dynamiczne elementy, które są ładowane z bazy danych jako ciąg znaków, który wygląda tak:RequireJS załadować ciąg

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

który jest tylko prosty moduł requireJS, jako ciąg znaków. Chcę leniwego wczytać powyższy skrypt za pomocą asynchronizacji wymaga połączenia. Tak więc mój główny skrypt requireJS wygląda następująco:

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

Jak załadować ten ciąg w requireJS? Wiem o wtyczce tekstowej, ale pozwala ona tylko ładować z plików. Próbowałem eval, ale nie rozwiązuje poprawnie zależności.

+0

proszę być jasne, prosząc pytanie. Proszę, prześlij swoje pytanie. –

+0

Och, czy naprawdę przechowujesz możliwy do oceny kod w bazie danych? –

+0

Tak. W moim przypadku było to rozszerzenie przeglądarki. Więc nie ma wyboru tworzenia punktu końcowego REST/zapisywania dynamicznego kodu w systemie plików. – bradnoriega

Odpowiedz

5

Jest to dość późno, ale po prostu pisać moje rozwiązanie tutaj w przypadku gdy ktoś potrzebuje.

Więc skończyło się pytanie na forum requireJS i zbadanie źródła text! plugin i json! plugin. Najczystszym sposobem na załadowanie modułu z String w RequireJS jest utworzenie własnej wtyczki do załadowania String, a następnie użycie onLoad.fromText(), który będzie eval ciąg i rozwiązać wszystkie zależności.

Przykład mojego pluginu (nazwijmy go db! plugin):

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

Następnie można użyć wtyczki jak:

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

Uwaga:

  1. Nie ma to droga do require() z ciągu bez numeru eval. To właśnie robi wewnętrznie onLoad.fromText(). Ponieważ eval jest złem, powinieneś go używać tylko wtedy, gdy wiesz, jaki String masz zamiar eval(). Jeśli używasz go w rozszerzeniu przeglądarki, możesz zrelaksować zasady CSP.
  2. Aby nazwać swój moduł String, można użyć explicit naming syntax. W ten sposób twój moduł będzie zawsze miał tę samą absolutną nazwę.
-1

Powinieneś być w stanie to zrobić:

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

To nie działa. Uruchamianie runme() nie rozwiązuje tylko zależności + tracimy zakres/zamknięcie oferowane przez require. – bradnoriega

0

Aby nieco bardziej bezpośrednio odpowiedzieć na pytanie, jak stworzyć plugin tak:

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

i używać go tak:

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

require(["load-string!" + world_module], 
    function(x){ 
     console.log("Hello "+x); 
    })