我们在项目中使用require.js,我们需要覆盖第705行中的setTimeout,这是我们需要忽略/忽略这个setTimeout 的代码(我的意思是在它上面运行),这个问题如果我改变了它在开源代码中显式,当我更改版本时,代码将丢失,我应该如何从外部仅为require.js文件覆盖此setTimout并保留它,只要我使用此lib,是否可以在JS全球优雅的方式?
https://github.com/jrburke/requirejs/blob/master/require.js
这是第705行
//If still waiting on loads, and the waiting load is something //other than a plugin resource, or there are still outstanding //scripts, then just try back later. if ((!expired || usingPathFallback) && stillLoading) { //Something is still waiting to load. Wait for it, but only //if a timeout is not already in effect. if ((isBrowser || isWebWorker) && !checkLoadedTimeoutId) { checkLoadedTimeoutId = setTimeout(function () { checkLoadedTimeoutId = 0; checkLoaded(); }, 50); } }
仅供参考,我们这样做的原因是 Chrome:超时/间隔在后台标签中暂停?
您已声明自己的目标是解决Chrome setTimeout
针对后台制表符执行的限制问题.我不认为这样做是个好主意,但如果你必须这样做,那么你一定要修补RequireJS而不是setTimeout
全局搞乱.你说:
如果我在开源代码中更改它,当我更改版本时,代码将丢失
仅当您不使用合理的方法执行更改时才会出现这种情况.可以理智地做到这一点.例如,您可以使用Gulp获取require.js
安装的文件node_modules
(在安装RequireJS之后npm
)并生成修补文件build
.然后在应用程序中使用此修补文件.这是gulpfile.js
:
var gulp = require("gulp"); // Bluebird is a good implementation of promises. var Promise = require("bluebird"); // fs-extra produces a `fs` module with additional functions like // `ensureDirAsync` which is used below. var fs = require("fs-extra"); // Make it so that for each the function in fs that is asynchronous // and takes a callback (e.g. `fs.readFile`), a new function that // returns promise is created (e.g. `fs.readFileAsync`). Promise.promisifyAll(fs); var to_replace = "if ((isBrowser || isWebWorker) && !checkLoadedTimeoutId) {\n\ checkLoadedTimeoutId = setTimeout(function () {\n\ checkLoadedTimeoutId = 0;\n\ checkLoaded();\n\ }, 50);"; var replace_with = "if (isBrowser || isWebWorker) {\n\ checkLoaded();"; gulp.task("default", function () { // Use `fs.ensureDirAsync` to make sure the build directory // exists. return fs.ensureDirAsync("build").then(function () { return fs.readFileAsync("node_modules/requirejs/require.js") .then(function (data) { data = data.toString(); // We use the split/join idiom to a) check that we get // the string to be replaced exactly once and b) // replace it. First split... var chunks = data.split(to_replace); // Here we check that the results of splitting the // chunk is what we expect. if (chunks.length < 2) { throw new Error("did not find the pattern"); } else if (chunks.length > 2) { throw new Error("found the pattern more than once"); } // We found exactly one instance of the text to // replace, go ahead. So join... return fs.writeFileAsync("build/require.js", chunks.join(replace_with)); }); }); });
您需要在运行npm install gulp fs-extra bluebird requirejs
之前运行它.无论如何,你可以使用Gulp,你可以使用Grunt,或者你可以使用你想要执行构建的任何其他系统.要点是:
您有一个可重现且自动化的方法来修补RequireJS.如果安装了新版本的RequireJS npm
,则在重建软件时,只要RequireJS的代码不会以阻止应用修补程序的方式更改,就会自动应用修补程序.如果更改阻止应用修补程序,请参阅下一点.
此方法比setTimeout
在运行时覆盖更强大.假设詹姆斯·伯克在决定向RequireJS重命名的新版本checkLoaded
,以checkDone
并重命名相关变量(这样checkLoadedTimeoutId
变成checkDoneTimeoutId
).上面的gulpfile会在你再次运行时引发异常,因为它找不到要替换的文本.您必须更新要替换的文本和替换文本,以便修补程序与新版本的RequireJS一起使用.这样做的好处是,您可以获得事先已发生变化的早期警告,并且需要查看补丁.您可能不会在游戏后期出现意外,也许在您已经向客户提供新版软件之后.
setTimeout
在运行时覆盖的方法将无声地无法完成其工作.他们将寻找一个包含的功能,checkLoadedTimeoutId
在新版本中不再存在.因此,他们只会让RequireJS的行为与默认情况相同.失败将是一个微妙的失败.(我已经使用建议的自定义版本运行RequireJS,setTimeout
项目在未优化的情况下加载了超过50个模块.我发现使用库存的setTimeout
RequireJS和使用自定义的RequireJS 之间没有明显区别setTimeout
.)
这种方法不会减慢每次使用的速度setTimeout
. setTimeout
由RequireJS以外的其他代码使用.无论你如何削减它,在自定义替换中添加代码setTimeout
开始在传递给它的每个函数中查找字符串将使所有使用setTimeout
更慢.