用 systemjs 替换 requirejs——变量在本地范围内不可见
Replacing requirejs with systemjs -- variables not visible in local scope
我正在尝试将我们的 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 模块,一个泄漏到全局 space,第二个试图使用第一个泄漏的内容。喜欢下面两个模块。
src/a.js
需要泄漏的模块并取决于该模块泄漏的内容:
define(["./b"], function () {
console.log("a loaded");
callback();
});
src/b.js
泄漏到全局 space:
// This leaks `callback` into the global space.
var callback = function () {
console.log("callback called");
}
define(["./b"], function () {
console.log("b loaded");
});
有了 RequireJS,上面的代码就可以工作了。哦,它设计得很糟糕因为b.js
不应该泄漏到全局space,但它会起作用。您将在控制台上看到 callback called
。
使用 SystemJS,上面的代码将不起作用。为什么? RequireJS 通过向 header 添加一个 script
元素来加载模块,并让 script
执行模块的代码,因此 callback
最终确实在全局 space 中如果您使用指向脚本的 src
属性编写了自己的 script
元素,它也会采用同样的方式。 (你会得到一个 "Mismatched anonymous define" 错误,但这是一个单独的问题,不需要在这里耽搁我们。)SystemJS,默认情况下,使用 eval
而不是创建 script
元素,这会改变代码的计算方式。 通常,这无关紧要,但有时确实如此。在手头的情况下,callback
不会在全局 space 中结束,模块 a
失败。
最终,您的 AMD 模块应该这样写,这样它们就不会使用全局 space 来相互传递信息。
但是,还有另一种解决方案可能对最终解决方案有用 stepping-stone。您可以使用 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
我正在尝试将我们的 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 模块,一个泄漏到全局 space,第二个试图使用第一个泄漏的内容。喜欢下面两个模块。
src/a.js
需要泄漏的模块并取决于该模块泄漏的内容:
define(["./b"], function () {
console.log("a loaded");
callback();
});
src/b.js
泄漏到全局 space:
// This leaks `callback` into the global space.
var callback = function () {
console.log("callback called");
}
define(["./b"], function () {
console.log("b loaded");
});
有了 RequireJS,上面的代码就可以工作了。哦,它设计得很糟糕因为b.js
不应该泄漏到全局space,但它会起作用。您将在控制台上看到 callback called
。
使用 SystemJS,上面的代码将不起作用。为什么? RequireJS 通过向 header 添加一个 script
元素来加载模块,并让 script
执行模块的代码,因此 callback
最终确实在全局 space 中如果您使用指向脚本的 src
属性编写了自己的 script
元素,它也会采用同样的方式。 (你会得到一个 "Mismatched anonymous define" 错误,但这是一个单独的问题,不需要在这里耽搁我们。)SystemJS,默认情况下,使用 eval
而不是创建 script
元素,这会改变代码的计算方式。 通常,这无关紧要,但有时确实如此。在手头的情况下,callback
不会在全局 space 中结束,模块 a
失败。
最终,您的 AMD 模块应该这样写,这样它们就不会使用全局 space 来相互传递信息。
但是,还有另一种解决方案可能对最终解决方案有用 stepping-stone。您可以使用 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