概述
我正在尝试使用 RequireJS将站点转换为AMD。该站点的大部分内容都依赖于在单独模块中定义的全局变量(主要是实用程序方法)。这给开发人员带来了严重的困难,因为模块并不总是在内容脚本之前加载。
理想的结果
我想要一种方法来防止在加载某些模块之前解析这些页内脚本,以便团队成员可以在时间允许的情况下慢慢删除它们。
研究
- 我注意到curl.js可以在同步模式下加载一些脚本。
- 我找不到 RequireJS 2+ 的类似内容,尽管我认为它曾经受支持。(我的 git foo 不够强大。)
注意事项
- 虽然我知道我可以在开发模式下通过脚本标签加载模块,但我宁愿不这样做,因为这需要在两个地方列出模块。
我试过的
所以我尝试生成一个轮询解决方案,它运行一个粗略定时的 while 循环,然后中断运行一个回调。这是我的实现:
(function (global) { // Making this into a global, so I don't need to wait for the loader's extra timeout.
var undef;
/**
* Simple args getter.
*
* @param {*} arg Used if defined.
* @param otherwise Used if arg is not defined.
* @return {*}
*/
var arg = function (arg, otherwise) {
return arg !== undef ? arg : otherwise;
};
/**
* Locks up the main thread as soon as the current thread completes.
*
* @param {number} time
*/
var lock = function (time) {
setTimeout(function () {
var start = +(new Date),
current = 0;
console.log('Locking thread at %d', start);
start += time;
while (start > (current = +(new Date))) {
console.log('tick');
}
console.log('Unlocking thread at %d', current);
}, 0);
};
/**
* Locks up the main thread until a condition is met, releasing it
* momentarily to allow other "threads" to advance.
*
* @param {Function} condition
* @param {number} [checkInterval=50] How long
*/
var lockThreadUntil = global.lockThreadUntil = function (condition, checkInterval, releaseDuration) {
checkInterval = arg(checkInterval, 50);
releaseDuration = arg(releaseDuration, 0);
var id = setInterval(function () {
if (!condition()) {
lock(checkInterval);
} else {
clearInterval(id);
}
}, releaseDuration);
};
define(function () {
return lockThreadUntil;
});
})(this);
在页面上(我测试了一个创建全局的模块):
(function (global) {
lockThreadUntil(function () {
var isLoaded = !!global.path && !!global.path.toModule;
if (!isLoaded) {
return false;
}
console.log('Is loaded!');
return true;
}, 1000);
})(this);
在内容脚本中:
console.log('Was needed!');
我希望这会导致 DOM 在给脚本加载时间的同时推进很少,从而允许它在内容脚本之前进入解析堆栈。不幸的是,内容中的脚本似乎首先被触发。
包起来
我愿意接受建议。我正在考虑的选项包括(看起来都很糟糕):
- 咬牙切齿地使用脚本标签。
- 吞下 RequireJS 加载方法并用 xhr 实现替换。