2015年需要/ AMD和异步资源

时间:2015-08-27 19:47:56

标签: asynchronous requirejs amd

我正在构建一个使用异步资源的库。我希望库可以加载AMD / require。

我从2011年开始看到有关承诺支持的this discussion,但它无处可去。 我看过像asyncrequire-promise这样的插件 - 但我不知道我对安装插件的库感觉如何。

我有兴趣知道在加载资源和/或依赖脚本方面是否有任何变化。如果不支持promises,是否有另一种方法可以通过异步方式告知requirejs脚本是否已准备就绪?

1 个答案:

答案 0 :(得分:0)

我潜入了require.js的源代码,我没有找到一种方法来进行异步定义。插件具有此功能,但简单的定义则没有。我认为背后的原因是异步循环依赖有点棘手。

然而,编写一个迷你异步需求库并非不可能:

(function(context) {
  const modules = new Map();

  function require(name) {
    return Promise.resolve(null).then(function() {
      const module = modules.get(name);
      if (!module) throw new Error("Undefined module");
      if (module.promise) {
        return module.exports;
      } else {
        return module.promise = Promise.all(
            module.deps.map(internalRequire)
          ).then(function(args) {
            return module.factory.apply(context, args);
          }).then(function(defExport) {
            if (defExport !== undefined) {
              module.exports.default = defExport;
            }
            return module.exports;
          });
      }
      function internalRequire(name) {
        return (name === 'exports') ? module.exports : require(name);
      }
    });
  }

  function define(name, deps, factory) {
    if (modules.has(name)) throw new Error("Redefined module");
    modules.set(name, {
      name: name,
      deps: deps,
      factory: factory,
      exports: {},
      promise: null
    });
  }

  context.require = require;
  context.define = define;
})(self);

用法:

define('A', ['B'], function(dep) {
    return new Promise(function(resolve) {
        setTimeout(function() {
            resolve("A(" + dep.default + ")");
        }, 100);
    });
});

define('B', ['C'], function(dep) {
    return new Promise(function(resolve) {
        setTimeout(function() {
            resolve("B(" + dep.default + ")");
        }, 100);
    });
});
define('C', ['A'], function(dep) {
    return new Promise(function(resolve) {
        setTimeout(function() {
            resolve("C(" + dep.default + ")");
        }, 100);
    });
});

require("A").then(function(s) {
    console.log(s);
});