2013-07-03 14 views
48

Có cách nào để xác định mô-đun "tự động" tải các mô-đun khác trong RequireJS không? Nếu có, cách trình tối ưu hóa (r.js) hiểu cách/khi một mô-đun phải được bao gồm?Yêu cầu động trong RequireJS, nhận được lỗi "Tên mô-đun chưa được tải cho bối cảnh"?

Ví dụ, chúng ta hãy dynModules một module trong đó xác định các cặp tên/đường dẫn:

define([], function() { 
    return ['moduleA', 'moduleB']; // Array of module names 
}); 

mô-đun khác là sẽ nạp module tự động, dựa trên mảng. Điều này sẽ không làm việc :

define(['dyn_modules'], function (dynModules) { 
    for(name in dynModules) { 
     var module = require(path); // Call RequireJS require 
    } 

    // ... 
}); 

... mang lại cho tôi:

Uncaught Error: Module name "moduleA" has not been loaded yet for context: _. Use require([]) http://requirejs.org/docs/errors.html#notloaded

tôi có thể giải quyết các lỗi, nhưng nó không phải là "năng động" nữa:

define(['dyn_modules', 'moduleA', 'moduleB'], function (dynModules) { 
    for(name in dynModules) { 
     var module = require(path); // Call RequireJS require 
    } 

    // ... 
}); 

Trả lời

61

Giới hạn liên quan đến cú pháp CommonJS được đơn giản hóa so với cú pháp gọi lại bình thường:

tải một module vốn đã là một quá trình không đồng bộ do thời gian không rõ của tải nó. Tuy nhiên, RequireJS trong mô phỏng đặc tả CommonJS phía máy chủ cố gắng cung cấp cho bạn một cú pháp đơn giản. Khi bạn làm điều gì đó như thế này:

var foomodule = require('foo'); 
// do something with fooModule 

gì đang xảy ra đằng sau hậu trường là RequireJS được nhìn vào cơ thể của mã chức năng của bạn và phân tích ra rằng bạn cần 'foo' và tải nó trước khi thực hiện chức năng của mình. Tuy nhiên, khi một biến hoặc bất kỳ thứ gì khác ngoài một chuỗi đơn giản, chẳng hạn như ví dụ của bạn ...

var module = require(path); // Call RequireJS require 

... thì Yêu cầu không thể phân tích cú pháp này và tự động chuyển đổi nó. Giải pháp là chuyển đổi sang cú pháp gọi lại;

var moduleName = 'foo'; 
require([moduleName], function(fooModule){ 
    // do something with fooModule 
}) 

Do ở trên, đây là một viết lại có thể xảy ra ví dụ 2 của bạn để sử dụng cú pháp tiêu chuẩn:

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: Từ câu trả lời của riêng bạn, tôi thấy bạn đang sử dụng gạch chân/lodash, do đó việc sử dụng _.values_.object có thể đơn giản hóa chuỗi lặp thông qua các đối số như trên.

+2

Cảm ơn thời gian của bạn, tôi đã tìm thấy một giải pháp sau khi tìm kiếm trên trang web RequireJS. Xem câu trả lời của tôi. – gremo

+0

Câu hỏi duy nhất tôi có là: sử dụng 'require (_. Values ​​(Config), ...)' là mã async, phải không? Điều đó có nghĩa là tôi cần sử dụng kiểu gọi lại khi 'require' kết thúc, đúng không? – gremo

+0

Có, và bạn đang sử dụng cú pháp gọi lại trong câu trả lời của bạn. 'require (_. values ​​(Config), hàm() {' tương đương với 'require (dynModules, function() {' trong mine. Cả hai đều sử dụng một chuỗi các chuỗi như tham số đầu tiên và cung cấp một hàm cho gọi lại là Tham số thứ 2. – explunit

5

Trả lời cho chính tôi. Từ trang web của RequireJS:

//THIS WILL FAIL 
define(['require'], function (require) { 
    var namedModule = require('name'); 
}); 

Điều này không thành công vì requirejs cần phải chắc chắn tải và thực thi tất cả các phụ thuộc trước khi gọi chức năng nhà máy ở trên. [...] Vì vậy, hoặc là không vượt qua trong mảng phụ thuộc, hoặc nếu sử dụng mảng phụ thuộc, liệt kê tất cả các phụ thuộc trong đó.

Giải pháp của tôi:

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

Bộ nạp:

define(['jade', 'lodash', 'config'], function (Jade, _, Config) { 
    var deps; 

    // Dynamic require 
    require(_.values(Config), function() { 
     deps = _.object(_.keys(Config), arguments); 

     // Use deps... 
    }); 
}); 
+0

Nope, 'modules 'là nghĩa vụ phải được định nghĩa trong một mô-đun khác, tức là một tập tin cấu hình Nó hoạt động tốt btw – gremo

+0

@explunit thấy câu trả lời cập nhật của tôi – gremo

+0

trông giống như khóa vẫn là chuyển đổi từ cú pháp đồng bộ CommonJS đến cú pháp gọi lại RequireJS – explunit

Các vấn đề liên quan