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#
эта ошибка только сегодня утром пришла мне на ум.