//Inside b.js: define(["require", "a"], function(require, a) { //"a" in this case will be null if a also asked for b, //a circular dependency. return function(title) { return require("a").doSomething(); } } );
一般说来你无需使用require()去获取一个模块,而是应当使用注入到模块函数参数中的依赖。循环依赖比较罕见,它也是一个重构代码重新设计的警示灯。但不管怎样,有时候还是要用到循环依赖,这种情形下就使用上述的require()方式来解决。
如果你熟悉CommonJS,你可以考虑使用exports为模块建立一个空object,该object可以立即被其他模块引用。在循环依赖的两头都如此操作之后,你就可以安全地持有其他模块了。这种方法仅在每个模块都是输出object作为模块值的时候有效,换成函数无效。
//Inside b.js: define(function(require, exports, module) { //If "a" has used exports, then we have a real object reference here. //However, we cannot useany of a's properties until after b returns a value. var a = require("a"); exports.foo = function () { return a.bar(); }; });
或者,如果你使用依赖注入数组的步骤,则可用注入特殊的"exports"来解决:
//Inside b.js: define(['a', 'exports'], function(a, exports) { //If "a" has used exports, then we have a real object reference here. //However, we cannot useany of a's properties until after b returns a value. exports.foo = function () { return a.bar(); }; });
§ 1.3.9 JSONP服务依赖
JSONP是在javascript中服务调用的一种方式。它仅需简单地通过一个script标签发起HTTP GET请求,是实现跨域服务调用一种公认手段。
为了在RequireJS中使用JSON服务,须要将callback参数的值指定为"define"。这意味着你可将获取到的JSONP URL的值看成是一个模块定义。
下面是一个调用JSONP API端点的示例。该示例中,JSONP的callback参数为"callback",因此"callback=define"告诉API将JSON响应包裹到一个"define()"中:
require(["http://example.com/api/data.json?callback=define"], function (data) { //The data object will be the API response for theJSONP data call. console.log(data); } );
仅支持返回值类型为JSON object的JSONP服务,其他返回类型如数组、字串、数字等都不能支持。
§ 2.机制
RequireJS使用head.appendChild()将每一个依赖加载为一个script标签。
RequireJS等待所有的依赖加载完毕,计算出模块定义函数正确调用顺序,然后依次调用它们。
在同步加载的服务端JavaScript环境中,可简单地重定义require.load()来使用RequireJS。build系统就是这么做的。该环境中的require.load实现可在build/jslib/requirePatch.js中找到。