当需要sleep like功能时如何重构javascript代码

How to refactor the javascript code when sleep like functionality needed?

本文关键字:重构 代码 javascript 何重构 sleep like 功能      更新时间:2023-09-26

我看到在SO中有很多关于请求javascript睡眠函数的线程,我知道它只能使用setTimeoutsetInterval

我用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函数并保持它可读(和工作)?

例如:

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

我有一个类似的问题,在一些旧的浏览器中,一个大循环阻塞了整个浏览器,我使用:

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是一个回调函数,当所有完成时调用。

经过一番研究,我认为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.