javascript - 用 systemjs 替换 requirejs——变量在本地范围内不可见

标签 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();
    });
}

我不得不删除一些前导 /让东西正确加载,这很好,但我现在遇到了一个问题,即在 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对象,然后调用 callbackFunction(dashboard)在上面。

最佳答案

您的问题可以简化为以下情况,您有两个 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 不应该泄漏到全局空间中,但它会起作用。您将在控制台上看到 调用的回调

使用 SystemJS,上面的代码将不起作用。为什么? RequireJS 通过将 script 元素添加到 header 来加载模块,并让 script 执行模块的代码,因此 callback 确实最终出现在全局空间中如果您使用指向您的脚本的 src 属性编写了自己的 script 元素,其方式将相同。 (你会得到一个“不匹配的匿名定义”错误,但这是一个单独的问题,不需要在这里耽搁我们。)SystemJS,默认情况下,使用 eval 而不是创建 script 元素,这会改变代码的计算方式。 通常,这无关紧要,但有时却很重要。在手头的情况下,callback 不会在全局空间中结束,并且模块 a 失败。

最终,您的 AMD 模块应该被编写成它们不会使用全局空间来相互传递信息。

但是,还有另一种解决方案可以用作最终解决方案的垫脚石。您可以使用 scriptLoad: true 告诉 SystemJS 使用 script 元素,就像 RequirejS 那样。 (有关详细信息和注意事项,请参阅 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

关于javascript - 用 systemjs 替换 requirejs——变量在本地范围内不可见,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47681070/

相关文章:

javascript - 无法向动态创建的元素添加类

javascript - 仪表条不更新

javascript - TinyMCE4 file_picker_callback - 返回附加参数

javascript - 使用 BackBone 查看 javascript 对象更改

requirejs - Intellisense for AMD/Requirejs in Visual Code

javascript - Vue 组件 Prop 的默认值以及如何检查用户是否没有设置 Prop ?

C++ 从类 B 中运行类 A 的函数指针作为回调

html - javascript中的回调函数问题

javascript - Require.js 要求/定义缺少参数的后果

javascript - AJAX 以多线程方式运行