Javascript For-Loop问题

时间:2012-11-10 14:39:30

标签: javascript asynchronous for-loop

我试图以200毫秒的间隔点击每个项目,我编写了以下脚本,但是For循环似乎存在问题。有人请告诉我你认为它有什么问题。

function clickLink(elm) {
    var evt = document.createEvent('MouseEvents');
    evt.initMouseEvent('click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
    elm.dispatchEvent(evt);
}

function sel() {
    elms = document.getElementsByClassName('uItem');
    var inputs= elms;
    var howbig= elms.length;
    console.log(howbig);

    for (var i=250;i<elms.length;i++)
    {
        setTimeout(clickLink(inputs[i]),200)
    };

页面上有1400个uItem。

7 个答案:

答案 0 :(得分:4)

最干净的解决方案就是让你的clickLink函数返回一个函数。

function clickLink(elm) {
    return function() {
        var evt = document.createEvent('MouseEvents');
        evt.initMouseEvent('click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
        elm.dispatchEvent(evt);
    };
}

如果你想要一个间隔,那么就会错开定时器:

var start = 250
for (var i=start;i<elms.length;i++) {
    setTimeout(clickLink(elms[i]), 200 * (i - start))
}

或者抛弃循环,然后使用setInterval

var i = 250,
    len = inputs.length;
var itvl = setInterval(function() {
    clickLink(elms[i++]);
    if (i >= len)
        clearInterval(itvl);
}, 200);

并返回原来的clickLink功能

答案 1 :(得分:2)

如果您使用的是中等版本的JavaScript,最简单的方法是使用bind。这将创建一个带有参数的单个函数对象,这些参数在调用bind时计算,而不是以后计算。因此,您想要的行是:

setTimeout( clickLink.bind( null, inputs[i] ),  /* delay expression here */ )

你可以明确地创建绑定函数,但它很丑陋,只有你强烈要求支持旧的JavaScript解释器时才应该这样做。

答案 2 :(得分:2)

ì的范围存在问题,延迟需要相应增加,i间隔为200毫秒,setTimeout期望函数为是争论。

    for (var i=250;i<elms.length;i++)
    {
        setTimeout((function() {
            var j = i // keep i as j in this closure
            return function() { // return the right function
                clickLink(inputs[j])
            }
        })(),200 * i) // set the delay depending on i
    };

答案 3 :(得分:2)

function sel() {
  var elems = document.getElementsByClassName('uItem');
  for (var i = 0; i < elems.length; i += 1) {
    setTimeout(function (el) {
      return function () {
        clickLink(el);
      };
    }(elems[i]), i * 1000);   
  };
}

演示:http://jsfiddle.net/4hYWy/


小注释:我不喜欢这些结构(如示例中那样计算延迟)。但它与原始代码非常接近,我选择的解决方案可能会使它过于复杂。

答案 4 :(得分:2)

此代码等待200ms,执行回调并准备一个200ms后执行的新回调。 第二次回调在sel调用后400ms执行,依此类推。

    var callback = function(i) {
        return function() {
            if (i < elms.length) {
                clickLink(inputs[i]);
                setTimeout(callback(i + 1), 200);
            }
        };
    };
    setTimeout(callback(250), 200);

答案 5 :(得分:1)

你这样做的方式不会让你每200毫秒点击一次,你几乎可以同时注册你的所有点击(循环最后一次迭代1000项,几乎立即)所以你基本上会得到你的1000 + aprox。点击几乎同时触发的事件,我认为这可能会导致问题,所以要确保它们在大约200毫秒内执行一次。这样做:

window.i=250;
for (var i=250;i<elms.length;i++)
{
setTimeout(function() {
   clickLink(inputs[window.i]);
   window.i++;
},200 * (i-249)); //Here we make sure events are spaciated 200ms each approx.
};

更新: 更新了anonymouse函数以传递i以避免在评论中注明关闭问题。

更新2 :在匿名函数中添加window.i以解决i范围问题

更新3 :更新了我上面的代码,以修复触发每次点击事件的时间间隔,我们使用的是200 * i,但这只有在i开始时才正确零,这里它从250开始,所以正确的形式是200 * (i-249)

尽管有一些评论,i范围问题是使用window.i解决的,请参阅此处的测试https://tinker.io/98fd4/1

答案 6 :(得分:1)

没有范围问题或计算正确的间隔。

function sel() {
    var elms = document.getElementsByClassName('uItem'),
        i = -1,
        I = elms.length,

        rec = function () {
            if ( i++ < I ) {
                clickLinks(elms[i]);
                setTimeout(rec, 200);
            }
        };

    rec();
}

http://jsfiddle.net/joplomacedo/cqfxH/