setTimeout не работает в пользовательском скрипте Greasemonkey, когда JS отключен в браузере

Я работаю над проектом, который требует, чтобы мой пользовательский скрипт запускался на страницах, поскольку они отображаются без выполнения любого из JavaScript страницы. То есть, нам нужно просматривать с отключенным JavaScript.

я столкнулся с проблемой, хотя, когда я пытаюсь отложить выполнение функции в моем скрипте. Всякий раз, когда я звоню window.setTimeout, функция, которую я передаю, никогда не выполняется.

Я думаю, что, возможно, эта функция на самом деле вызывается unsafeWindow вместо окна. Есть ли обходной путь для этого?

Я должен упомянуть, что звонки setTimeout работать нормально, когда JavaScript включен, и все остальное в моем скрипте работает нормально без включения JavaScript.

Спасибо за вашу помощь!

3 ответов


хотя JavaScript Greasemonkey работает с повышенными привилегиями, как сказал Pointy,setTimeout функции добавляются в пространство JavaScript страницы - при необходимости закрываются. (В нормальной работе экземпляр Greasemonkey часто исчезает к тому времени, когда какие-либо таймеры, он установил, пожар.)

Итак, если основной JavaScript страницы отключен, таймер никогда не будет работать.

способы:

  • использовать GM_xmlhttpRequest как грубая задержка. Вы можно настроить страницу, которая намеренно рисует свой ответ. Так код:

    GM_xmlhttpRequest
    (
        {
            method: "GET",
            url:    "http://YourTestServer.com/DelayService.php?Seconds=2",
            onload: function (response) {YourDelayedFunctionHere (); }
        }
    );
    

    вызовет служебную страницу, которую вы настроили, чтобы сделать задержку для вас.

  • используйте NoScript, чтобы отключить все JavaScript страницы, кроме главной страницы. Например, для страницы, YourSite.com/testpage.htm, который включает в себя скрипты, скажем,*SpamGenerator.net ... разрешить скрипты из YourSite.com но заблокируйте их SpamGenerator.net.


на window ссылка по-прежнему является window, просто завернутый в обертку песочницы. Когда вы звоните setTimeout на нем вы все еще настраиваете что-то для запуска страницей. Я полагаю, что это должно быть так, что браузер не будет запускать эти события таймаута вообще (или просто проигнорирует события), когда Javascript отключен.


это может быть исправлено так:

вы можете сказать " нет " NoScript + setTimeout = failed

на greasemonkey.js найти [ injectScripts ]: функция..... добавьте наш GM-api.....

добавить этот код:

sandbox.setTimeOut = function (callback, timeout, p1,p2,p3/*....*/){
    var args = Array.prototype.slice.call(arguments,2);
    return  sandbox.window.setTimeout(function(){
        return callback.apply(sandbox, args);
    } ,timeout);
}

или

sandbox.setInterval = function (callback, timeout, p1,p2,p3/*....*/){
    var args = Array.prototype.slice.call(arguments,2);
    return sandbox.window.setInterval(function(){
        return callback.apply(sandbox, args);
    } ,timeout);
}

этот код работает нормально, я использовал его с мая 2010 года.

на user.js вы можете проверить это так:

setTimeout(alert,1000, 'i am happy');
var loopid = setInterval(alert, 1000, 'I am happy again');
setTimeout(clearInterval, 5000, loopid);

var j=300;
for(;~j;j--){ //running perfectly!
    setTimeout(alert, 1000+20*j, 'I am happy' )
}

решение 2

sandbox.kk_setTimeout = function (func, timeout, repeat_type, p1,p2,p3/*....*/){
    var callback = { k100: sandbox };
    var args = Array.slice.call(arguments,3);

    // repeat_type:  0=once  1=repeatng, after fired stopped    2=always repeat
    if(repeat_type!=2){
        callback.notify = function (timer){ func.apply(this.k100,args); }
        var timerCC = Components.Constructor("@mozilla.org/timer;1", "nsITimer", 'initWithCallback');
        var R = repeat_type?1:0;
    } else {
        callback.observe = function (subject, topic, data) { func.call(this.k100); };
        var timerCC = Components.Constructor("@mozilla.org/timer;1", "nsITimer", 'init'); 
        var R = 2; 
    }
    return new timerCC(callback, timeout, R);
}

// now have to test it:

var test100 = kk_setTimeout(alert, 1000, 0, 'i am timer');  //running = setTimeout
var test100 = kk_setTimeout(alert, 1000, 2, 'i am timer');  //running = setInterval
test100.cancal() ;   //clear it by cancel() method

kk_setTimeout(alert, 1000+20*j, 2, 'i am happy' );
var j=300;
for(;~j;j--){
    kk_setTimeout(alert, 1000+20*j, 0, 'i am happy 2' );
}

//bug:
//this solution 2 running after about 3-8 times differently stop, why bug ? i don't know.
// you will fail to use many times(over 3-8 time) kk_timeout(); or using repeat_type = 2 after fired 3-8 times timeout
//or running total time max about 20-30 seconds stop 
//--- this maybe stop by option in about:config -- about [max javascript run time]

Китай-kkmove залатанный


правка, чтобы добавить...

сорри всем,

есть еще несколько патчей к коду, который я забыл написать:

sandbox.window = sandbox._proto_; // add this line also to the solution 1#

эта ошибка только сегодня утром пришла мне на ум.