本文介绍了覆盖require.js中的setTimeout的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们在项目中使用require.js,我们需要覆盖第705行中的 setTimeout ,这是我们需要忽略/忽略这个代码总是setTimeout(我的意思是在它上面运行),问题是如果我在开源代码中更改它时显式更改版本代码将丢失,我应该如何从外部仅为require.js文件覆盖此setTimout保持它只要我使用这个lib,是否可以在全球JS中以优雅方式进行?

we are using require.js in our project and we need to override the setTimeout in line 705 , this is the code which we need to ignore/omit somehow this setTimeout at all(I mean run over it) ,the problem that if I change it in the open source code explicit when I change version the code will be lost,How should I override this setTimout from outside only for the require.js file and keep it as long as I use this lib, is it possible to do it in elegant way in JS globally ?

这是第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);
            }
        }

仅供参考,我们这样做的原因是

FYI ,The reason that we do it isChrome: timeouts/interval suspended in background tabs?

推荐答案

您已经说明了您的目标是解决Chrome在 setTimeout 用于后台标签。我不认为这样做是个好主意,但如果你必须这样做,那么你绝对应该修补RequireJS而不是全局搞乱 setTimeout 。你说:

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:

仅当您不使用合理的方法执行更改时才会出现这种情况。可以理智地做到这一点。例如,您可以使用Gulp获取 node_modules 中安装的 require.js 文件(在使用 npm )并在 build 中生成修补文件。然后在应用程序中使用此修补文件。这是 gulpfile.js

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));
            });
    });
});

你需要运行 npm install gulp fs-extra bluebird requirejs 。无论如何,你可以使用Gulp,你可以使用Grunt,或者你可以使用你想要执行构建的任何其他系统。要点是:

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:


  1. 您有一个可重复且自动化的方法来修补RequireJS。如果您安装新版本的RequireJS与 npm ,当您重建软件时,补丁会自动应用,只要RequireJS的代码不会以阻止应用补丁的方式更改。如果更改阻止应用修补程序,请参阅下一点。

  1. 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.

此方法比覆盖 setTimeout更强大在运行时。假设James Burke决定使用较新版本的RequireJS将 checkLoaded 重命名为 checkDone 并重命名关联的变量(以便 checkLoadedTimeoutId 变为 checkDoneTimeoutId )。上面的gulpfile会在你再次运行时引发异常,因为它找不到要替换的文本。您必须更新要替换的文本和替换文本,以便修补程序与新版本的RequireJS一起使用。这样做的好处是,您可以获得事先已发生变化的早期警告,并且需要查看补丁。 游戏后期不会出现意外,也许是在您已经向客户提供新版软件之后。

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.

在运行时覆盖 setTimeout 的方法将无声地无法完成其工作。他们将寻找一个包含 checkLoadedTimeoutId 的函数,它在新版本中将不再存在。因此,他们只会让RequireJS的行为与默认情况相同。失败将是一个微妙的失败。 (我已经使用建议的自定义版本 setTimeout 运行RequireJS,项目在未优化的情况下加载了超过50个模块。我发现RequireJS使用库存之间没有明显区别 setTimeout 和RequireJS使用自定义 setTimeout 。)

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.)

此方法不会减慢每次使用 setTimeout setTimeout 由除RequireJS之外的其他代码。无论你如何削减它,在自定义替换中添加代码到 setTimeout 开始在传递给它的每个函数中查找字符串将使所有使用 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.

这篇关于覆盖require.js中的setTimeout的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-24 05:45