Как реорганизовать код javascript, когда требуется функциональность, похожая на сон?

Я вижу, что здесь в SO много тем о запросе функции сна javascript, и я знаю, что это можно сделать только с использованием setTimeout и setInterval.

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

var html0=syncGet(url0); // custom function for sync ajax call.
// fill the something array
for(var i=0;i<something.length;i++)
{
   // calculate url1,url2 using the array and the i variable
   // do something with lots of local variables
   var html1=syncGet(url1);
   // I would put a sleep here.
   // do something with the results
   var html2=syncGet(url2);
   // I would put a sleep here.
   // do something with the results
   // get url3 from the page loaded from url2
   var html3=syncGet(url3);
   // I would put a sleep here.
   // do something with the results
}
// use the result of the for loop and lots of code will follow...

Фактический код немного сложнее и длиннее этого.

Я плачу за несуществующую функцию сна (и понимаю, почему это невозможно). Как реорганизовать это, чтобы использовать функции setTimeout, setInterval и сохранить его читаемым (и рабочим)?


person Calmarius    schedule 29.04.2011    source источник


Ответы (3)


У меня была аналогичная проблема, когда большой цикл блокировал весь браузер в некоторых старых браузерах, я решил ее, используя:

function handlenext(idx,length) {
    idx++

    //do your stuff here base on idx.


    if (idx < length) {
        setTimeout(function(){handlenext(idx,length)},1)
    } else {
        initSuccessEnd()
    }
}

var ln = something.length;


if (ln>0) {
    handlenext(0,ln);
} else {
    initSuccessEnd()
}

здесь initSuccessEnd — это функция обратного вызова, вызываемая, когда все закончено..

person dwarfy    schedule 29.04.2011

Например это:

var urls = ["your","u","r","l´s"];
var htmls = new Array(urls.length);
var time = 1000;
for(var i=0;i<urls.length;i++){
    (function(i){
        setTimeout(function(){
            htmls[i] = syncGet(urls[i]);
            if(i == urls.length-1){
                //continue here
            }
        },time*i);
    })(i);
}
person Van Coding    schedule 29.04.2011

После исследования я думаю, что новый итератор-генератор Mozilla может быть наиболее подходящим. (Поддерживается начиная с FF2)

function doSomething()
{
   //.....
      var html=syncGet(url1);
      yield true;
      var html2=syncGet(url2);
      yield true;
      var html3=syncGet(url3);
      yield true;
   //......
   yield false;
}

function iteratorRunner(iterator,timeout)
{
    if (iterator.next()) 
    {
       setTimeout(function(){iteratorRunner(iterator,timeout)},timeout);
    }
    else
    {
       iterator.close();
    }
}

var iterator=doSomething(); // returns an iterator immediately
iteratorRunner(iterator,1000); // runs the iterator and sleeps 1 second on every yield.

Я надеюсь, что грильманки справится с этим...

person Calmarius    schedule 30.04.2011
comment
Greasemonkey не может справиться с этим ... пффф - person Calmarius; 05.05.2011