如何创建和依赖异步JavaScript模块?

时间:2017-02-04 21:17:52

标签: javascript asynchronous module promise

有几种方法可以在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!。虽然我不确定这是否是最佳解决方案,因为我需要手动跟踪所有这些依赖项。

所以我的问题是:处理此类异步模块依赖项的最佳方法是什么?有没有标准化的方法呢?

1 个答案:

答案 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模块而言,这个建议完全没有用,这些模块目前没有全局异步功能。