System JS在一次调用中加载多个依赖项

时间:2014-03-10 02:42:08

标签: javascript systemjs

查看systemjs的文档,我找不到同时加载多个依赖项的示例。我希望api类似于......

System.import(['jquery.js','underscore.js']).then(function($, _) {
    // ready to go with both jQuery and Underscore...
});

我希望它能使用promises并行加载所有依赖项,并在完成所有依赖项后执行回调。这可能吗?如果没有,是否有理由没有实现此功能?

4 个答案:

答案 0 :(得分:15)

Promise.all可以做到这一点:

Promise.all([
    System.import('jquery'),
    System.import('underscore')
]).then(function(modules) {
    var jquery = modules[0];
    var underscore = modules[1];
});

但你可以看到它很难看。有人认为在规范级别允许像你的例子这样的数组,但它需要在模块规范中,因为这是一个规范加载器。

更好的选择实际上是只有一个应用程序入口点app.js,然后具有该加载依赖项。

答案 1 :(得分:3)

这就是我要这样做的方式,一点一点地说:它没有经过测试。

var SystemImport = System.import;
System.import = function (name, options) {
    if (Object.prototype.toString.call(name) !== '[object Array]')
        return SystemImport.apply(this, arguments);
    var self = this,
        imports = Promise.all(name.map(function (name) {
            return SystemImport.call(self, name); // should i pass options ?
        }));
    return {
        then: function (onfulfill, onreject) {
            return imports.then(function (dependencies) {
                return onfulfill.apply(null, dependencies);
            }, onreject);
        }
    };
};

此代码段将使用自身的包装版本替换System.import,允许使用依赖项数组。

它返回一个“thennable”对象,这应该适用于任何兼容的promise实现。

由于.spread方法不在Promise A +规范中,这是我能想到的最符合规范的方式......

答案 2 :(得分:2)

可能最短且最干劲的方式是将[].map()应用于System.import,然后对其结果进行解构:

Promise.all([
    'jquery',
    'underscore'
].map(url => System.import(url))).then(function ([$, _]) {
    // do stuff with results
});

请记住,在撰写本文时,Destructuring仍需要编译。

如果你不想转发,你可以编写自己的包装和传播脚本:

function spread(callback) {
    return function (args) {
        return callback.apply(undefined, args);
    }
}
function import(deps) {
    return Promise.all(deps.map(function (url) {return System.import(url);}));
}

并加载它:

import(['jquery', 'underscore']).then(spread(function ($, _) { /*...*/ }));

答案 3 :(得分:0)

我一直在找同样的事情。 我目前正在使用Bluebird,Promise.all和Promise.spread来做到这一点。 这就像我写的那样“好看”。

Promise.all([
  SystemJS.import('jquery'),
  SystemJS.import('axios')
]).spread(function(jquery, axios){
  return jquery < axios;
});