有几种方法可以在JavaScript中创建和导入模块,但据我所知,它们都设计为同步加载。
为了展示我面临的问题,我创建了这两个示例CommonJS模块:
var Dependency;
(function (Dependency) {
Dependency.data = 'Not loaded!';
function doSomethingAsync() {
// Fetching data from server...
setTimeout(function () {
Dependency.data = 'Loaded!';
}, 2000);
}
})(Dependency = exports.Dependency || (exports.Dependency = {}));
此模块包含一些异步代码,在“加载”时不能(/不应该)使用。尝试使用其他模块中的data
时,它将无效:
var dep = require("./dependency");
var MyModule;
(function (MyModule) {
function useDependency() {
// Logs out 'Not loaded!'
console.log(dep.Dependency.data);
}
MyModule.useDependency = useDependency;
})(MyModule = exports.MyModule || (exports.MyModule = {}));
致电MyModule.useDependency()
会显示Dependency
尚无法使用。
我正在寻找一种方法来实现一个通用结构,以便在我的项目中使用。
我想出的解决方案是使用(ES6)承诺。我给每个模块一个load()
函数,它都返回一个promise。所以在这种情况下,我会从某种条目文件中调用Dependency.load().then(MyModule.load)
。在这种情况下,这样可以正常工作,因为useDependency()
现在会打印出Loaded!
。虽然我不确定这是否是最佳解决方案,因为我需要手动跟踪所有这些依赖项。
所以我的问题是:处理此类异步模块依赖项的最佳方法是什么?有没有标准化的方法呢?
答案 0 :(得分:1)
我正在寻找一种方法来实现一个通用结构,以便在我的项目中使用。
由于您使用的是Common.js模块,因此最好和最简单的方法是使每个导出(使用异步初始化的模块)成为承诺本身。
(当然,如果它只是模块中的一个函数,那么只有该函数才能返回一个promise)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li>First
<ul>
<li>Second
<ul>
<li>Third
<ul>
<li>Fourth</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
// dependency.js
var promise = new Promise(resolve => {
// Fetching data from server...
setTimeout(function () {
resolve('Loaded!')
}, 2000);
});
module.exports = promise.then(data => {
…
return {
data,
…
};
});
// mymodule.js
module.exports = Promise.all([
require("./dependency"),
…
]).then(([dep, …]) => {
…
return {
useDependency() {
console.log(dep.data); // 'Loaded'
},
…
};
});
请注意,这不适用于循环依赖项。
对于ES6模块而言,这个建议完全没有用,这些模块目前没有全局异步功能。