为什么事件处理程序要等到触发代码执行完毕?
Why does event handler wait until triggering code completes execution?
以下片段说明了我的问题。我有一些代码为 customeventstart
事件调用 jQuery.trigger
,然后进行一些密集处理,然后它再次为 customeventstop
事件调用 jQuery.trigger
。
我希望 customeventstart
的事件处理程序立即执行。但是,在控制台显示 customeventstart
处理程序的结果之前存在明显的延迟。似乎在触发代码执行完毕后才调用事件处理程序。
注意:您可以根据机器的处理能力将代码片段中的循环迭代次数调整为 lengthen/shorten 延迟。
btn = $('#btn');
btn.on('click', function() {
btn.trigger('customeventstart');
// intensive/time-consuming processing
for (var i = 0; i < 100000000; ++i) {
'string' + 'concatenation';
}
console.log('intensive processing done');
btn.trigger('customeventstop');
});
btn.on('customeventstart', function() {
console.log('starting');
});
btn.on('customeventstop', function() {
console.log('stopping');
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="btn">This may take a while</button>
我打算使用异步 Web Workers 解决方案,但我想更好地了解发生了什么。
为什么 jQuery.trigger
ed 事件的处理程序等待或似乎等待触发代码完成?
我认为这与 Firefox(和 Firebug)中的 console.log
实施有关,而不是事件的实际时间。
我尝试对您的代码片段进行以下修改,基本上只是添加 Date.now
和更多的控制台日志语句:
btn = $('#btn');
btn.on('click', function() {
console.log(Date.now() + ': triggering customeventstart');
btn.trigger('customeventstart');
// intensive/time-consuming processing
console.log(Date.now() + ': starting intensive processing');
for (var i = 0; i < 100000000; ++i) {
'string' + 'concatenation';
}
console.log(Date.now() + ': intensive processing done');
console.log(Date.now() + ': triggering customeventstop');
btn.trigger('customeventstop');
});
btn.on('customeventstart', function() {
console.log(Date.now() + ': starting');
});
btn.on('customeventstop', function() {
console.log(Date.now() + ': stopping');
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="btn">This may take a while</button>
对我来说:
在 Chrome 和 IE11 上,单击按钮会导致前三个日志语句(通过 "starting intensive processing")的近乎即时的记录,然后是延迟,然后是其余的行。顺序和时间由线上的时间戳证实。
在 Firefox 上,单击按钮会导致延迟,然后所有行一起出现 — 但如果您查看时间戳,很明显延迟实际上发生在 "starting intensive processing" 之间和 "intensive processing done" 与 Chrome 和 IE11 一样的日志语句(我必须在循环最大值中添加一个 0 才能在 Firefox 中看到这一点——哇,这些天这些东西很快):
"1424713006530: triggering customeventstart"
"1424713006530: starting"
"1424713006531: starting intensive processing"
"1424713007263: intensive processing done"
"1424713007263: triggering customeventstop"
"1424713007264: stopping"
所以并不是事件在延迟后被触发,而是如果主 UI 线程繁忙,Firefox 的 console.log
实现似乎会被暂停。
这与主 UI 线程繁忙时浏览器可能不会更新页面显示的常见情况非常相似。例如,在下面的代码片段中,我们在进行密集处理时将按钮的背景变为红色(根本不使用任何自定义事件),然后在完成后恢复它;但是在大多数浏览器上,即使在处理过程中有足够的时间,您也根本看不到按钮的背景发生变化:
btn = $('#btn');
btn.on('click', function() {
console.log(Date.now() + ': turning button background red');
btn.css('background-color', 'red');
// intensive/time-consuming processing
console.log(Date.now() + ': starting intensive processing');
for (var i = 0; i < 100000000; ++i) {
'string' + 'concatenation';
}
console.log(Date.now() + ': intensive processing done');
console.log(Date.now() + ': restoring button background');
btn.css('background-color', '');
});
(Look in the console.)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="btn">This may take a while</button>
以下片段说明了我的问题。我有一些代码为 customeventstart
事件调用 jQuery.trigger
,然后进行一些密集处理,然后它再次为 customeventstop
事件调用 jQuery.trigger
。
我希望 customeventstart
的事件处理程序立即执行。但是,在控制台显示 customeventstart
处理程序的结果之前存在明显的延迟。似乎在触发代码执行完毕后才调用事件处理程序。
注意:您可以根据机器的处理能力将代码片段中的循环迭代次数调整为 lengthen/shorten 延迟。
btn = $('#btn');
btn.on('click', function() {
btn.trigger('customeventstart');
// intensive/time-consuming processing
for (var i = 0; i < 100000000; ++i) {
'string' + 'concatenation';
}
console.log('intensive processing done');
btn.trigger('customeventstop');
});
btn.on('customeventstart', function() {
console.log('starting');
});
btn.on('customeventstop', function() {
console.log('stopping');
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="btn">This may take a while</button>
我打算使用异步 Web Workers 解决方案,但我想更好地了解发生了什么。
为什么 jQuery.trigger
ed 事件的处理程序等待或似乎等待触发代码完成?
我认为这与 Firefox(和 Firebug)中的 console.log
实施有关,而不是事件的实际时间。
我尝试对您的代码片段进行以下修改,基本上只是添加 Date.now
和更多的控制台日志语句:
btn = $('#btn');
btn.on('click', function() {
console.log(Date.now() + ': triggering customeventstart');
btn.trigger('customeventstart');
// intensive/time-consuming processing
console.log(Date.now() + ': starting intensive processing');
for (var i = 0; i < 100000000; ++i) {
'string' + 'concatenation';
}
console.log(Date.now() + ': intensive processing done');
console.log(Date.now() + ': triggering customeventstop');
btn.trigger('customeventstop');
});
btn.on('customeventstart', function() {
console.log(Date.now() + ': starting');
});
btn.on('customeventstop', function() {
console.log(Date.now() + ': stopping');
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="btn">This may take a while</button>
对我来说:
在 Chrome 和 IE11 上,单击按钮会导致前三个日志语句(通过 "starting intensive processing")的近乎即时的记录,然后是延迟,然后是其余的行。顺序和时间由线上的时间戳证实。
在 Firefox 上,单击按钮会导致延迟,然后所有行一起出现 — 但如果您查看时间戳,很明显延迟实际上发生在 "starting intensive processing" 之间和 "intensive processing done" 与 Chrome 和 IE11 一样的日志语句(我必须在循环最大值中添加一个 0 才能在 Firefox 中看到这一点——哇,这些天这些东西很快):
"1424713006530: triggering customeventstart" "1424713006530: starting" "1424713006531: starting intensive processing" "1424713007263: intensive processing done" "1424713007263: triggering customeventstop" "1424713007264: stopping"
所以并不是事件在延迟后被触发,而是如果主 UI 线程繁忙,Firefox 的 console.log
实现似乎会被暂停。
这与主 UI 线程繁忙时浏览器可能不会更新页面显示的常见情况非常相似。例如,在下面的代码片段中,我们在进行密集处理时将按钮的背景变为红色(根本不使用任何自定义事件),然后在完成后恢复它;但是在大多数浏览器上,即使在处理过程中有足够的时间,您也根本看不到按钮的背景发生变化:
btn = $('#btn');
btn.on('click', function() {
console.log(Date.now() + ': turning button background red');
btn.css('background-color', 'red');
// intensive/time-consuming processing
console.log(Date.now() + ': starting intensive processing');
for (var i = 0; i < 100000000; ++i) {
'string' + 'concatenation';
}
console.log(Date.now() + ': intensive processing done');
console.log(Date.now() + ': restoring button background');
btn.css('background-color', '');
});
(Look in the console.)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="btn">This may take a while</button>