用systemjs替换requirejs - 在本地范围

时间:2017-12-06 18:25:12

标签: javascript callback requirejs systemjs

我试图将requirejs来电转换为使用SystemJS,但我并不完全确定我做错了什么。

我们的原始电话如下:

return function(callback) {
    requirejs(["/app/shared.js"], function(result){
        callbackFunction = callback;
        callback(dashboard);
        main();
    })
}

而我正在尝试的是:

return function(callback) {
    console.log(callback.toString())
    SystemJS.import('app/shared.js').then(function(result){
        callbackFunction = callback;
        callback(dashboard);
        main();
    });
}

我必须删除一些前导/以便正确加载内容,这很好,但我现在遇到了一个问题,其中变量是在{的顶部定义的{1}}在我的本地shared.js文件中无法显示。在我的浏览器控制台中,我得到:

main.js

Potentially unhandled rejection [1] ReferenceError: dashboard is not defined定义shared.js

dashboard

我想我有两个问题:

  • 这是替换var dashboard = { rows: [], } // Other definitions... define(["/app/custom-config.js", /* etc */]); 来电的正确方法吗?
  • 如果是这样,为什么requirejs的变量无法访问?

要获得更完整的图片,shared.js只需设置main()对象,然后在其上调用dashboard

1 个答案:

答案 0 :(得分:2)

您的问题可以简化为以下情况:您有两个AMD模块,一个泄漏到全局空间,第二个尝试使用第一个泄漏的模块。像以下两个模块一样。

src/a.js要求泄漏的模块取决于该模块泄漏的内容:

define(["./b"], function () {
    console.log("a loaded");
    callback();
});

src/b.js泄漏到全球空间:

// This leaks `callback` into the global space.
var callback = function () { 
  console.log("callback called");
}
define(["./b"], function () {
    console.log("b loaded");
});

使用RequireJS,上面的代码将起作用。哦,设计错误因为b.js不应泄漏到全局空间,但它会起作用。您将在控制台上看到callback called

使用SystemJS,上面的代码不起作用。为什么? RequireJS通过向标头添加script元素来加载模块,并允许script执行模块的代码,以便callback最终在全局空间中以与完全相同的方式结束如果您编写了自己的script元素,其中src属性指向您的脚本。 (你得到一个"不匹配的匿名定义"错误,但这是一个单独的问题,不需要在此处扣留我们。) SystemJS,默认使用eval而不是创建script元素,这会改变代码的评估方式。通常情况下,无关紧要,但有时也会如此。在这种情况下,callback不会在全局空间中结束,模块a会失败。

最终,您的AMD模块应该编写,以便他们不会使用全局空间来传递彼此的信息。

然而,还有另一种解决方案可用作最终解决方案的垫脚石。您可以使用scriptLoad: true告诉SystemJS使用像RequirejS那样的script元素。 (有关详细信息和警告,请参阅meta上的文档。)以下是执行此操作的配置:

System.config({
    baseURL: "src",
    meta: {
        "*": {
            scriptLoad: true, // This is what fixes the issue.
        }
    },
    packages: {
        // Yes, this empty package does something. It makes `.js` the
        // default extension for modules.
        "": {}
    },
});

// We have to put `define` in the global space to 
// so that our modules can find it.    
window.define = System.amdDefine;

如果我在没有scriptLoad: true的情况下运行此处给出的示例代码,则模块a无法调用回调。使用scriptLoad: true,它可以调用回调,然后我进入控制台:

b loaded
a loaded
callback called