Dynamiczne Wymaganie w RequireJS, uzyskanie błędu "Nazwa modułu nie została jeszcze załadowana dla kontekstu"?
Czy istnieje sposób na zdefiniowanie modułu, który "dynamicznie" ładuje inne moduły w RequireJS? Jeśli tak, to w jaki sposób optymalizator (r.js) rozumie, w jaki sposób/kiedy moduł musi być dołączony?
Na przykład niech dynModules
moduł definiujący pary nazwa / Ścieżka:
define([], function () {
return ['moduleA', 'moduleB']; // Array of module names
});
Inny moduł będzie dynamicznie ładował Moduły, bazując na tablicy. To nie zadziała :
define(['dyn_modules'], function (dynModules) {
for(name in dynModules) {
var module = require(path); // Call RequireJS require
}
// ...
});
... daje:
Uncaught Error: Nazwa modułu "moduleA" nie została jeszcze załadowana dla kontekst:_. Użyj wymagaj([]) http://requirejs.org/docs/errors.html#notloaded
Mogę rozwiązać błąd , ale to już nie jest "dynamiczne":
define(['dyn_modules', 'moduleA', 'moduleB'], function (dynModules) {
for(name in dynModules) {
var module = require(path); // Call RequireJS require
}
// ...
});
2 answers
Ograniczenie odnosi się do uproszczonej składni CommonJS vs. normalnej składni wywołania zwrotnego:
- http://requirejs.org/docs/whyamd.html#commonjscompat
- https://github.com/jrburke/requirejs/wiki/Differences-between-the-simplified-CommonJS-wrapper-and-standard-AMD-define
Ładowanie modułu jest z natury procesem asynchronicznym z powodu nieznanego czasu jego pobierania. Jednak Wymagajjs w emulacji po stronie serwera CommonJS spec stara się podać uproszczoną składnię. Kiedy robisz coś takiego:
var foomodule = require('foo');
// do something with fooModule
To, co dzieje się za kulisami, to to, że RequireJS patrzy na treść kodu funkcji i analizuje, że potrzebujesz " foo " i ładuje go przed wykonaniem funkcji. Jednak, gdy zmienna lub cokolwiek innego niż prosty ciąg znaków, takich jak twój przykład...
var module = require(path); // Call RequireJS require
...następnie Require nie jest w stanie tego przetworzyć i automatycznie przekonwertować. Rozwiązaniem jest konwersja na składnia wywołania zwrotnego;
var moduleName = 'foo';
require([moduleName], function(fooModule){
// do something with fooModule
})
Biorąc pod uwagę powyższe, oto jeden z możliwych przepisań twojego drugiego przykładu użycia standardowej składni:
define(['dyn_modules'], function (dynModules) {
require(dynModules, function(){
// use arguments since you don't know how many modules you're getting in the callback
for (var i = 0; i < arguments.length; i++){
var mymodule = arguments[i];
// do something with mymodule...
}
});
});
EDIT: z twojej własnej odpowiedzi widzę, że używasz podkreślenia / lodash, więc użycie _.values
i _.object
może uprościć zapętlanie tablicy argumentów jak powyżej.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-07-03 13:37:45
Odpowiadam przed sobą. Ze strony Wymagajs:
//THIS WILL FAIL
define(['require'], function (require) {
var namedModule = require('name');
});
To się nie powiedzie, ponieważ requirejs musi upewnić się, że załaduje i wykona wszystkie zależności przed wywołaniem powyższej funkcji factory. [...] Tak więc albo nie przekazuj tablicy zależności, albo jeśli używasz tablicy zależności, wymień w niej wszystkie zależności.
Moje rozwiązanie:
// Modules configuration (modules that will be used as Jade helpers)
define(function () {
return {
'moment': 'path/to/moment',
'filesize': 'path/to/filesize',
'_': 'path/to/lodash',
'_s': 'path/to/underscore.string'
};
});
The loader:
define(['jade', 'lodash', 'config'], function (Jade, _, Config) {
var deps;
// Dynamic require
require(_.values(Config), function () {
deps = _.object(_.keys(Config), arguments);
// Use deps...
});
});
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-07-03 13:27:27