概述如何实现一个简单的浏览器端js模块加载器(2)

// main.html zmm.use('/a.js', function(){...}); // a.js define('/b.js', function(b) { var a = 1; a = b + 1; return a; }); // b.js define('/a.js', function(a) { var b = a + 1; return b; });

就会陷入a等待b加载完成、b等待a加载完成的死锁状态。sea.js碰到这种情况也是死锁,也许是默认这种行为不应该出现。

seajs里可以通过require.async来缓解循环依赖的问题,但必须改写a.js:

// a.js define('./js/a', function (require, exports, module) { var a = 1; require.async('./b', function (b) { a = b + 1; module.exports = a; //a= 3 }); module.exports = a; // a= 1 }); // b.js define('./js/b', function (require, exports, module) { var a = require('./a'); var b = a + 1; module.exports = b; }); // main.html seajs.use('./js/a', function (a) { console.log(a); // 1 });

但这么做a就必须先知道b会依赖自己,且use中输出的是b还没加载时a的值,use并不知道a的值之后还会改变。

在浏览器端,似乎没有很好的解决方案。node模块加载碰到的循环依赖问题则小得多。

node/CommonJS

CommonJS模块的重要特性是加载时执行,即脚本代码在require的时候,就会全部执行。CommonJS的做法是,一旦出现某个模块被"循环加载",就只输出已经执行的部分,还未执行的部分不会输出。

// a.js var a = 1; module.exports = a; var b = require('./b'); a = b + 1; module.exports = a; // b.js var a = require('./a'); var b = a + 1; module.exports = b; // main.js var a = require('./a'); console.log(a); //3

上面main.js的代码中,先加载模块a,执行require函数,此时内存中已经挂了一个模块a,它的exports为一个空对象a.exports={};接着执行a.js中的代码;执行var b = require('./b');之前,a.exports=1,接着执行require(b);b.js被执行时,拿到的是a.exports=1,b加载完成后,执行权回到a.js;最后a模块的输出为3。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wwfsgj.html