почему этот вызов setTimeout () работает в консоли, а не как сценарий greasemonkey? - PullRequest
1 голос
/ 09 сентября 2011

Когда я использую setTimeout () в цикле for () в скрипте greasemonkey, он вообще не работает. Тем не менее, точно такой же код работает нормально, если я запускаю его в консоли Firebug. Вот код:

// ==UserScript==
// @name           setTimeout test
// @include        *
// @run-at         document-end
// ==/UserScript=


function test(delaytime) {
    alert("test called with "+delaytime);
}

function test2() {
  for( var i = 0; i < 100; i+= 10 ) {
    setTimeout('test('+i+');', i);
  }
}

setTimeout(test2,10);

Если я заменю цикл for () явными вызовами, подобными приведенным ниже, то он будет работать нормально.

setTimeout(function() { test( 0); },  0);
setTimeout(function() { test(10); }, 10);
setTimeout(function() { test(20); }, 20);
setTimeout(function() { test(30); }, 30);
setTimeout(function() { test(40); }, 40);
setTimeout(function() { test(50); }, 50);
setTimeout(function() { test(60); }, 60);
setTimeout(function() { test(70); }, 70);
setTimeout(function() { test(80); }, 80);
setTimeout(function() { test(90); }, 90);

Какая разница? Есть ли какой-нибудь способ, которым я могу заставить сгенерированный цикл forTimeouts работать в greasemonkey?

Ответы [ 2 ]

3 голосов
/ 09 сентября 2011

Потому что, когда строка очищается во время запуска setTimeout для выполнения функции, цикл запускает свой курс, а i сидит на последнем значении цикла.

Заморозитьзначение i для каждого вызова setTimeout, вам нужно захватить его в закрытии функции следующим образом:

function test2() {
  for( var i = 0; i < 100; i+= 10 ) {
    setTimeout(function(val) {
        return(function() {test(val);});
    } (i), i);
  }
}

Это также имеет то преимущество, что избавляется от eval в параметре setTimeout.

1 голос
/ 09 сентября 2011

Вы должны продублировать значение i в локальной переменной:

function test2() {
  for( var i = 0; i < 100; i+= 10 ) {
    (function(i){
        setTimeout('test('+i+');', i);
    })(i);
  }
}

Примечание: Вы должны передать анонимную функцию в setTimeout вместо передачи ей строки (которая будет оценена). Так намного быстрее:

function test2() {
    for( var i = 0; i < 100; i+= 10 ) {
        (function(i){
            setTimeout(function(){
                test(i);
            }, i);
        })(i);
    }
}
...