You've stated your goal is to work around the throttling that Chrome performs on setTimeout
for tabs that are in the background. I do not think it is a good idea to do so but if you must, then you should definitely patch RequireJS instead of messing with setTimeout
globally. You said:
if I change it in the open source code explicit when I change version the code will be lost
This is true only if you do not use a sensible method to perform the change. It is possible to do it sensibly. For instance, you can use Gulp to take the require.js
file installed in node_modules
(after you install RequireJS with npm
) and produce a patched file in build
. Then you use this patched file in your application. Here is the 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));
});
});
});
You need to have run npm install gulp fs-extra bluebird requirejs
before running it. At any rate, you can use Gulp, you can use Grunt, or you can use any other system you want to perform a build. The points are:
You have a reproducible and automated method to patch RequireJS. If you install a new version of RequireJS with npm
, when you rebuild your software the patch is applied automatically, so long as the code of RequireJS does not change in a way that prevents applying the patch. See the next point for what happens if a change prevents applying the patch.
This method is more robust than overriding setTimeout
at runtime. Suppose James Burke decides in a newer version of RequireJS to rename checkLoaded
to checkDone
and renames the associated variables (so that checkLoadedTimeoutId
becomes checkDoneTimeoutId
). The gulpfile above will raise an exception when you run it again because it won't find the text to be replaced. You'll have to update the text to be replaced and the replacement so that the patch works with the new version of RequireJS. The benefit here is that you get an early warning that things have changed and that you need to review the patch. You won't have a surprise late in the game, perhaps after you've already delivered a new version of your software to clients.
The methods that override setTimeout
at run time will just silently fail to do their job. They'll be looking for a function that contains checkLoadedTimeoutId
, which won't exist anymore in the new version. So they will just let RequireJS behave the way it does by default. The failure will be a subtle one. (I've run RequireJS with the proposed custom versions of setTimeout
with a project that loads upwards of 50 modules when not optimized. I saw no discernible difference between RequireJS using the stock setTimeout
and RequireJS using a custom setTimeout
.)
This method does not slow down every use of setTimeout
. setTimeout
is used by other code than RequireJS. No matter how you cut it, adding code in a custom replacement to setTimeout
that starts looking for strings in each function passed to it will make all uses of setTimeout
slower.