当处于循环中时,如何处理Javascript事件

3

我用jQuery编写了如下程序:

$(document).ready(function(){
    var k = 0;
    setTimeout(function(){alert("Hello")},500);
    for (var i = 0; i < 5000; ++i) {
        ++k;
        $('.inner').append('<p>Test</p>' + k.toString());
    }
});

我原本以为定时器事件会在循环执行期间执行警报“Hello”字符串的功能,但它只有在循环结束后才会发生。
这是语言特定的问题吗?当在某个循环/执行内部时应该如何实现回调函数处理?

你的示例中没有事件处理程序。你实际上想要实现什么? - T.J. Crowder
你实际上想要实现什么? - usoban
1
JavaScript 只有一个执行线程,即使您设置了 0 的超时时间,函数的代码仍将在 setTimeout 的回调之前执行。 - bert
“当我在某个循环/执行内部时,应该如何实现回调函数处理?”请详细说明您实际需要什么。 - sabithpocker
2个回答

10
你忽略了 JavaScript 内部结构中一个重要的特征:事件循环。所有函数都存储在那里等待执行。此外,JavaScript(一般情况下 - 不包括 AJAX 和 workers)是单线程的,因此任何时候只能执行一个函数。
对于你的脚本:事件队列中的第一个函数是你的 ready() 回调。它被执行并在执行时将许多其他函数(来自 setTimeout() 调用的回调)放置在事件队列中。但是为了执行这些函数,第一个函数必须完成,也就是说整个循环必须完成并且函数必须返回。
所以基本上会发生以下情况(每个项目的第二行表示当前事件循环状态):
1. 只有 ready 回调排队等待执行。
ready()-callback
2. setTimeout 回调被放置在事件队列中。
ready()-callback | setTimeout()-callback
3. 所有循环都完成了。
ready()-callback | setTimeout()-callback
4. ready() 回调已经完成并从队列中删除。
setTimeout()-callback
5. 现在执行 setTimeout() 回调并看到你的 alert() 消息!
setTimeout()-callback
因此,为了在循环执行之间的某个时间获得 alert(),您需要在第2500次迭代之后执行它。
$(document).ready(function(){
    var k = 0;
    for (var i = 0; i < 5000; ++i) {
        ++k;
        $('.inner').append('<p>Test</p>' + k.toString());
        if( i == 2500 ) {
          alert( 'Hello' );
        }
    }
});

或者将所有这些插入项也放在setTimeout()回调中(如果想要访问外部的k,则需要某种闭包):

$(document).ready(function(){
    var k = 0;
    setTimeout(function(){alert("Hello")},500);
    for (var i = 0; i < 5000; ++i) {
        ++k;
        setTimeout( (function( k ) { 
          $('.inner').append('<p>Test</p>' + k.toString());
        })( k ), 0 );
    }
});

1
是的,这是一个语言问题。在JavaScript中,setTimeout在指定的毫秒数后执行代码,例如500毫秒。它将脚本排队并继续执行下一行代码,因此您的循环将在等待500毫秒执行警报的同时执行。
如果您想让for循环在500毫秒后运行,请这样做
setTimeout(function(){
    for (var i = 0; i < 5000; ++i) {
        ++k;
        $('.inner').append('<p>Test</p>' + k.toString());
    }
},500);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接