Com os módulos AMD, quando (ou por que) está OK usar require () dentro do define ()?
Pergunta
Meu entendimento dos módulos AMD (usando, por exemplo, RequireJs ou curl.js) é:
require()
é usado para carregar módulos diferentes de forma assíncrona e, quando carregado, o retorno de chamada fn é executado.
E para definir um módulo, você teria scripts separados que usam define()
Mas eu vi alguns módulos usar require()
dentro de sua definição de função, por exemplo,
define([a, b, c], function(i, ii, iii){
require([d, e, f], function(d, e, f) {
// do some stuff with these require()'d dependancies
})
/* rest of the code for this module */
})
Mas acho isso confuso porque eu teria pensado que se um módulo tivesse dependências, então elas deveriam ser passadas por meio da função principal define([dependancies], fnDefinition)
e não dentro dela por meio de require()
conforme o exemplo acima está fazendo.
Existe um raciocínio por trás disso?
Solução
Existem alguns motivos pelos quais você pode querer usar require()
em um módulo.
Mas primeiro, certifique-se de solicitar uma referência à variável require
correta. Em seu exemplo, a referência a require
é global . Você quer uma referência a um require
que tem como escopo o contexto do seu módulo (às vezes chamado de "requer local"). Isso é fácil:
define(["a", "b", "c", "require"], function(i, ii, iii, require){
require(["d", "e", "f"], function(moduleD, moduleE, moduleF) {
// do some stuff with these require()'d dependencies
})
/* rest of the code for this module */
});
O principal motivo para isso ser importante é garantir que os IDs de módulo relativos (por exemplo, "./peerModule" ou "../unclePath/cousinModule") sejam resolvidos corretamente. (Este é um dos motivos, curl.js não tem um require
global por padrão.)
Razões para usar um require
local:
- você não sabe quais módulos são necessários no momento da compilação (ou no momento do carregamento) devido às condições de tempo de execução
- você deseja adiar explicitamente o carregamento de alguns módulos até que sejam necessários
- você deseja carregar uma variação de um módulo com base nos resultados da detecção de recursos (embora algo como o plug-in "tem!" do dojo possa ser uma solução melhor (desculpe, link me iludindo))
Por último, a AMD define um segundo uso de require
para compatibilidade com módulos criados em CommonJS Modules / 1.1 que são então agrupados em um define
. Eles se parecem com isto:
define(function(require, exports, module){
var a = require("pkgZ/moduleA"), // dependency
b = require("pkgZ/moduleB"); // dependency
/* rest of the code for this module */
});
Os desenvolvedores de javascript do lado do servidor podem achar esse formato atraente. :)
Alguns carregadores AMD (como RequireJS 0.2+, dojo 1.7+, bdLoad e curl.js 0.6+) detectarão este formato AMD / CJSM1.1 híbrido e encontrarão dependências examinando o módulo para chamadas require
.